使用SETNX锁防止缓存血崩

SETNX是Redis中的一个指令,全称是“Set If Not Exist”,只有当key不存在的时候,才会给key设置value,否则不进行任何操作。SETNX也可以用来实现Redis中的锁。

问题引入

在介绍如何使用SETNX实现锁之前,先让我们考虑这么一个问题:

假设我们现在有一个热点数据,数据存储在mysql中,我们使用redis做了一层缓存,在某个时间点缓存失效,这时候有大量的请求到来,他们同时到达,因为缓存miss,有可能同时把请求打到mysql,可能会出现血崩现象,那么如何避免这个问题的发生?

解决方式

答案就是使用锁,我们可以在缓存miss去mysql拿数据的时候用一把锁,保证缓存失效只会去mysql请求一次。

参照官方文档SETNX - Redis说明,我们可以使用

SETNX lock.foo <current Unix time + lock timeout + 1>

如果返回1,表示我们成功得到了锁,并且锁在lock timeout秒后就会invalid,这时候我们就可以去mysql拿数据并将其缓存。

如果返回0,表示锁已被占,可以重试或是去做别的事情。

死锁的处理

下面是原文对死锁现象的描述:

In the above locking algorithm there is a problem: what happens if a client fails crashes, or is otherwise not able to release the lock? It's possible to detect this condition because the lock key contains a UNIX timestamp. If such a timestamp is equal to the current Unix time the lock is no longer valid. When this happens we can't just call DEL against the key to remove the lock and then try to issue a SETNX, as there is a race condition here, when multiple clients detected an expired lock and are trying to release it.

如果客户端在SETNX返回0之后都等待若干时间,然后DEL lock.foo,然后重新SETNX,会有问题吗?

C1 and C2 read lock.foo to check the timestamp, because they both received
0 after executing SETNX, as the lock is still held by C3 that crashed after holding the lock.
C1 sends DEL lock.foo
C1 sends SETNX lock.foo and it succeeds
C2 sends DEL lock.foo
C2 sends SETNX lock.foo and it succeeds

both C1 and C2 acquired the lock because of the race condition.

确实会有上述的问题,C1和C2同时到达,可能会同时获得锁,那有什么解决方案么?

Fortunately, it's possible to avoid this issue using the following algorithm. Let's
see how C4, our sane client, uses the good algorithm:
C4 sends SETNX lock.foo in order to acquire the lock
The crashed client C3 still holds it, so Redis will reply with 0 to C4.
C4 sends GET lock.foo to check if the lock expired. If it is not, it will sleep for
some time and retry from the start.
Instead, if the lock is expired because the Unix time at lock.foo is older than
the current Unix time, C4 tries to perform:

GETSET lock.foo <current Unix timestamp + lock timeout + 1>
Because of the GETSET semantic, C4 can check if the old value stored atkey
is still an expired timestamp. If it is, the lock was acquired.
If another client, for instance C5, was faster than C4 and acquired the lock
with the GETSET operation, the C4 GETSET operation will return a non
expired timestamp. C4 will simply restart from the first step. Note that even if
C4 set the key a bit a few seconds in the future this is not a problem.

关键地方在于GETSET指令,能够在设置时间戳的时候判断该时间戳是否被修改过,如果被修改过,就返回0,保证不会有两个客户端同时设置了新的时间戳。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • Correctness AdapterViewChildren Summary: AdapterViews can...
    MarcusMa阅读 8,855评论 0 6
  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的阅读 13,447评论 5 6
  • 2017-3-22 1.在公车或地铁上有被骚扰过吗? 暂时没——什么想骚扰我,不是泼妇就是gay 2.你现在的离你...
    baiyun520960阅读 138评论 0 0
  • 走了这么久,真正的朋友有几个?我不傻、只是不想说… … 我不喜欢勾心斗角,不喜欢被算计,不喜欢假假的友情 我喜欢简...
    g小胖阅读 230评论 0 1