基于 Redis 和 ZooKeeper 的分布式锁

Redis 锁

SET key value EX 120 NX
  
该命令是原子操作,表示只有在 key 不存在的情况下,才会赋值成功,并且 120 秒后会自动删除,这样就实现了带超时时间的互斥锁功能,获得锁的程序删除 key 就是释放了锁,如果程序出错退出,达到超时时间后也会保证锁能被释放
  
这种方法在比较极端的情况下可能失效
  程序 A 获取锁
  master 将数据同步到 slave 之前 master 宕机了
  slave 被选为 master 且没有 A 的锁
  程序 B 获取锁成功,这时候程序 A 还在正常运行,导致两个程序同时获得锁

Redisson

https://redisson.org/
Redis Java Client with features of In-Memory Data Grid
Redisson 是基于 redis 的一个 Java 程序,提供了非常丰富的功能,其中就包括了锁
  
Redisson 提供了多种锁,具体可参考官网
https://github.com/redisson/redisson/wiki/8.-distributed-locks-and-synchronizers
  
这里以基本的 Lock 为例子

RLock lock = redisson.getLock("myLock");

// traditional lock method
lock.lock();

// or acquire lock and automatically unlock it after 10 seconds
lock.lock(10, TimeUnit.SECONDS);

// or wait for lock aquisition up to 100 seconds 
// and automatically unlock it after 10 seconds
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       lock.unlock();
   }
}
ZooKeeper 锁

ZooKeeper 的节点叫 ZNode,共有 4 种类型

  1. 持久节点 (PERSISTENT)
  2. 持久节点顺序节点(PERSISTENT_SEQUENTIAL)
  3. 临时节点(EPHEMERAL)
  4. 临时顺序节点(EPHEMERAL_SEQUENTIAL)

通过创建临时节点获取锁
  只有节点不存在时才能创建成功
  临时节点只有在 client 和 server 保持连接的时候才存在,session 断开后会被 server 删除
  阻塞模式下,可以设置获取锁的超时时间,没能成功获取会抛异常
  似乎没有可以设置成功获取锁后多长时间内会自动释放
  删除节点就是释放锁
  存在程序还在跑但 session 断开的异常情况要处理
  
通过创建临时顺序节点获取锁
  同一个节点下的临时顺序节点,会按照创建的先后顺序编号,可以实现排队机制
  程序 A B C 先后在同一个节点下创建临时顺序节点
  程序在成功创建后会检查所有临时顺序节点,判断自己是不是编号最小的
  A 程序发现自己是最小的于是 A 拿到锁
  B 程序发现 A 的编号在自己之前,于是等待并通过 watcher 监听 A 创建的节点
  C 程序发现 B 的编号在自己之前,于是等待并通过 watcher 监听 B 创建的节点
  A 程序删除节点释放锁
  B 程序通过 watcher 得知,并再次检查自己是否编号最小,如果是就获取锁
  B 程序删除节点释放锁
  C 程序通过 watcher 得知,并再次检查自己是否编号最小,如果是就获取锁
  
ZooKeeper 的性能应该会比 Redis 差些

# coding=utf-8
from kazoo.client import KazooClient
from kazoo.client import KazooState

zk = KazooClient(host="localhost:2181")
zk.start()


def my_listener(state):
    if state == KazooState.LOST:
        print("KazooState.LOST")
    elif state == KazooState.SUSPENDED:
        print("KazooState.SUSPENDED")
    else:
        print("KazooState.CONNECTED")


zk.add_listener(my_listener)


# 通过直接创建节点获取锁
try:
    zk.create('/test/lock/resource', b'app name', makepath=True, ephemeral=True, sequence=False)
except:
    print("failed to get the lock")
    exit()

zk.delete('/test/lock/resource')


# 通过三方包的功能获取锁
lock = zk.Lock('/test/lock/resource', b'app name')
if lock.acquire(blocking=True, timeout=None, ephemeral=True):
    # acquire 函数会使用 sequence=True 在 /test/lock/resource 节点下用包含 uuid 的名字创建子节点,这样节点必然创建成功
    # 如果子节点序号不是最小且 blocking=True 则注册 watcher 然后等待,否则序号最小则返回 True,不是最小或异常则返回 False
    # 如果超过了 timeout 时间还没获取则返回 False
    pass
else:
    print("failed to get the lock")
    exit()

# release 函数会 delete 节点
lock.release()




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

推荐阅读更多精彩内容