Redis锁_分析redis锁的实现原理

1.redis锁介绍

   一般来说,在对数据进行"加锁"时,程序首先需要通过获取(acquire)锁来得到对数据进行排他性访问的能力,然后才能对数据执行一系列操作, 最后还要将锁释放release给其他程序。对于能够被多个线程访问的共享内存数据结构(shared-memory data  structure)  来说,这种“先获取锁,然    后执行操作,最后释放锁”的动作非常常见。

  分布式锁也有类似的“首先获取锁,然后执行操作,最后释放锁”的动作,但这种锁既不是给同一个进程中的多个线程使用,也不是给同一台机器上 的多个进程使用,而是由不同机器上的不同Redis客户端进行获取和释放的。


2.实现redis锁要解决的4个问题


如果想要实现一个稳定的高性能的可用的redis锁,我们就不得不解决下面提到的4个问题。

实现redis锁,必须要解决的问题:

    (1).持有锁的进程因为操作时间过长而导致锁被自动释放,但进程本身并不知晓这一点,甚至还可能会错误地释放掉了其他进程持有的锁。

    (2).一个持有锁并打算执行长时间操作的进程已经崩溃

    (3).在一个进程持有的锁过期之后,其他多个进程同时尝试去获取锁,并且都获得了锁

    (4).第(1)种和第(3)种情况同时出现,导致多个进程获得了锁,而每个进程都以为自己是唯一一个获得锁的进程。



3.setnx命令和set命令以及getset命令


我们在实现redis锁时,会使用到set、setnx、getset这三个命令。关于这三个命令的使用,请查看:

setnx命令

getset

set命令

等熟悉了,这三个命令之后,我们就可以开始手写一个简易版的redis锁。


4.简易锁


为了对数据进行排他性访问,程序首先要做的就是获取锁。SETNX命令天生就适合用来实现锁的获取功能,这个命令只会在键不存在的情况下为键设置值,而锁要做的就是将一个随机生成的128位UUID设置为键的值,并使用这个值来防止锁被其他进程取得。


简易的redis锁

上述代码的逻辑:

首先,它会使用setnx命令,尝试在代表锁的键不存在的情况下,为键设置一个值,以此来获取锁;在获取锁失败的时候,函数会在给定 的时限内进行重试,直到成功获取锁或者超过给定的时限为止。(默认的重试时限为10秒)。


补充说明:

   注意,从Redis 2.6.12开始,redis的SET命令已经开始支持多个选项了:

    SET resource_name my_random_value NX PX 30000

    选项说明:

      EX    seconds    --set  the specified expire time ,in second

      PX    milliseconds  --set  the specified expire time in miliseconds

      NX                  --Only  set  the key if it does not already exist

      XX                  --Only set the key if it already exist

  所以,我们推荐使用set命令来取代之前的setnx命令。


解决的问题:

要解决的问题:

由于锁的持有者在崩溃的时候不会自动释放锁,这将导致锁一直处于已被获取的状态。

解决方案:

   为了给锁加上超时限制特性,程序将在取得锁之后,调用expire命令来为锁设置过期时间,使得redis可以自动删除超时的锁。为了确保锁在客    户端已经崩溃(客户端在执行介于setnx和expire之间的时候崩溃是最糟糕的)的情况下仍然能够自动被释放,客户端会在尝试获取锁失败之后,检  查锁的超时时间,并为未设置超时时间的锁设置超时时间。因此,锁总会带有超时时间, 并最终因为超时而自动被释放,使得其他客户端可以继续尝试获取已被释放的锁。

需要注意的一点是,因为多个客户端在同一时间内设置的超时时间基本上都是相同的,所以即使有多个客户端同时为同一个锁设置 超时时间,锁的超时时间也不会产生太大变化。



为锁加上超时时间,防止由于锁的持有者崩溃而导致的锁无法释放问题

新的这个acquireLockWithTimeout()函数给锁增加了超时限制特性,这一特性确保了锁总会在有需要的时候被释放,而不会被某个客户端一直把持着。


释放锁:


在释放锁的时候,要解决的问题是:

(1).持有锁的进程因为操作时间过长而导致锁被自动释放,但进程本身并不知晓这一点,甚至还可能会错误地释放掉了其他进程持有的锁。


释放锁时,可能出现的问题





5.锁由于超时而被自动释放


假如 我们把锁的释放操作控制在锁的持有者手里,让其尽可能多地在持有者完成任务的情况下,手动释放锁,而不是由于锁的超时机制来自动释放。

因为无论在哪种模式下,只要出现" 锁持有者尚未完成当前工作,但锁已经被自动释放"这种情况,都会造成并发问题。

那么为了,解决这个问题,我们能不能手动地把锁的超时时间尽可能地设置大一点呢???


遗留问题


备注:

  上面的代码都是伪代码,有些不是很严谨,主要表达的是redis锁的实现思路和原理。

 另外,对于redis实现分布式锁,还有一些问题,没有弄太明白,等弄清楚了,再补充一版。


官方的Redis分布式锁实现,请参考redlock:    redlock

At this point  we need to better  specify  our  mutual exclusion rule:  it is guaranteed  only as long as the client  holding the lock will terminate  its work within  the lock validity  time(as obtained in step 3),minus  some time (just a few  milliseconds in order to compensate for clock drift between processes).

要想保证redis分布式锁的可靠性和安全性,我们必须假定一个前题,那就是: 持有锁的线程能在锁的有效期内完成它的业务处理工作。



保证redis锁安全性的前提

下面再给出几个关于redis分布式锁的blog:

martin.kleppmann_how to do distributed lock

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

推荐阅读更多精彩内容