Redis实现分布式锁
加锁流程:
需要注意的点:
- 判断key是否存在
- 保存key-value
- 设置key的过期时间
这三部必须是原子操作,否则可能会有以下几种情况发生:
- 判断key是否存在,得出不存在的结果,保存key-value之前,另一个客户端也执行相同逻辑并且判断了key不存在,此时它也同样会创建并获得相同的锁。
- 设置key的过期时间之前,程序发生崩溃,导致设置过期时间失败,这可能会导致死锁或者占用资源时间过长。
所幸目前我们使用的redis版本都支持set key value [EX seconds] [PX milliseconds] [NX|XX]
此操作为原子操作!这样原来分三步且不能出问题的三步,变成了一步原子操作!!!这样就规避了我们上面提到的情况。
具体代码如下。
1 | import uuid |
解锁流程:
跟加锁一样,判断key是否存在和判断是否持有锁和删除key-value都必须是一组原子操作。
否则,当客户端判断key存在并且判断自己有锁,redis的过期时间到了,锁被redis自动释放,同时另一个客户端通过这个key加锁成功,如果第一个客户端执行了key-value操作,则这个不属于第一个客户端的锁就会被释放。
这一步需要用到lua脚本,鉴于我对lua不熟悉。以下释放锁的部分我借鉴于https://zhuanlan.zhihu.com/p/112016634,这里有提到如何通过lua脚本释放分布式锁。
1 | def release_lock(conn, lock_name, identifier): |
以上就是我学习redis分布式锁的全部内容。