redis实现分布式锁

什么是分布式锁

分布式锁是控制不同系统访问共享资源的一种锁机制,保证共享资源的可用、准确。

分布式锁需要具备什么条件

1.互斥(必须):同一时刻,分布式部署的应用中,同一个方法/资源只能被一台机器上的一个线程占用。

2.锁失效保护(必须):出现客户端断电等异常情况,锁仍然能被其他客户端获取,防止死锁。

3.可重入(可选):同一个线程在没有释放锁之前,如果想再次操作,可以直接获得锁。

4.阻塞/非阻塞(可选):若没有获取到锁,返回获取失败

5.高可用、高性能(可选):获取释放锁最好是原子操作,获取释放锁的性能要好

分布式锁的实现有哪些

1.基于数据库实现

2.基于缓存(redis,memcached)实现

3.基于zookeeper实现

redis实现方案

本篇文章我们先来讲讲redis的实现方案。

version1

lock:SETNX key value

unlock:DEL key [key ...]

指令含义参考:http://doc.redisfans.com/string/setnx.html

这是第一版最简单的方案,保证在没有出现任何异常的时候多个客户端可以使用分布式锁。

但是问题来了,如下图中所示,client2在获取锁之后突然挂了,这时候锁k将无法释放,其他client就永远拿不到这把锁了。这就是需要解决的锁失效保护问题。

version2

我们可以给锁引入一个过期时间,这样即使client2挂了,锁过期之后其他client仍然能用。

EXPIRE key seconds

但此时同样会存在一些问题:

1)误删

解决方法是每个client塞给锁的value设定为唯一的随机字符串,在删除的时候先get一把,如果还是这个字符串的话才去删。

2)过期时间需大于业务执行时间,不然任务还没搞完就被别人抢了

这个时候需要开启另外一个线程专门去刷新锁的过期时间。

version3

我们需要尽量保证获取、释放锁的操作是原子性的,才能避免极端的异常情况。

原子性地加锁

SET key uniquevalue NX EX 20

原子性地解锁

我们可以使用原生的lua脚本

if redis.call("get",KEYS[1]) == ARGV[1] then

    return redis.call("del",KEYS[1])

else

    return 0

// java

public void unlock() {

    // 使用lua脚本进行原子删除操作

    String checkAndDelScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +

                                "return redis.call('del', KEYS[1]) " +

                                "else " +

                                "return 0 " +

                                "end";

    jedis.eval(checkAndDelScript, 1, lockKey, lockValue);

}

version4

对于阻塞/非阻塞的要求,我们可以根据自己的业务特性,如果要阻塞,使用while循环调用;如果要非阻塞,这次调用失败,就需要增加事后的补偿机制。

对于可重入的特性,在一个线程获取到锁之后,可以把当前主机信息和线程信息保存起来,下次再获取之前先检查自己是不是当前锁的拥有者。


总结

通过redis实现分布式锁的必要可选条件之后,方案基本成型了,这个方案可以提供很好的性能。但是对于超时时间的设置,以及集群部署redis避免单点问题等还需要进一步优化。

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

推荐阅读更多精彩内容