Redis实现的分布式锁
# 对资源key加锁,key不存在时创建,并且设置,10秒自动过期
SET key value EX 10 NX
# 删除key
DEL key
NX的作用
NX参数是为了保证当分布式锁不存在时,只有一个client能写入次key成功,获取到锁。
分布式锁的第一核心要素就是互斥性、安全性,在同一时间内,不允许多个client同时获得锁
未设置key的自动过期时间
分布式锁的第二个核心要素,活性。在实现分布式锁的过程中要考虑到client可能会出现crash或者网络分区,需要原子申请分布式锁以及设置锁的自动过期时间,
通过过期、超时等机智自动释放锁,避免死锁,导致业务中断。
设置过期时间,仍然出现超卖
Redis分布式锁的是实现是阻塞的请求执行完成后,不能保证原子性操作,可以通过lua脚本来实现redis比较库存、扣件库存操作的原子性。
为什么喜欢用redis做分布式锁
Redis的核心优点是快、简单、部署方便。
Redis分布式锁的问题
Redis分布式锁存在的问题:
- 1.存在单点故障问题,官方给出了 解决的方法,就是RedLock算法。
- 2.获取锁失败后,只能抛出异常,不能阻塞线程。Redisson 开源框架解决了这些问题。
分布式锁创建的方案
Zookeeper是一个典型的分布式元数据存储服务,它的分布式锁实现基于Zookeeper的临时节点和顺序特性。
临时节点具备数据自动删除的功能,当client和Zookeeper连接和session断掉时,相应的临时节点就会被删除。
Zookeeper也提供了Watch特性可监听key的数据变化。
etcd分布式锁实现
事务与锁的安全性
etcd的事务特性有IF语句、ELSE语句、THEN语句组成,IF语句支持比较key的是修改版本号mod_version和创建版本号create_version.
可以通过key的创建版本号create_version来检查key是否存在,如果不存在,create_revision的版本号是0。
Lease与锁的活性
Lease是一种活性检测机制,提供了检测各个客户端存活的能力。
通过Lease机制就可以优雅地解决了client出现crash故障、client与etcd集群网络出现隔离等各类故障场景下的死锁问题,超过Lease TTL,就会自动释放。
Watch与锁的可用性
watch提供高效的数据监听能力,当client收到watch delete事件后,就可以快速判断自己是否有资格获取锁,极大减少了锁的不可用时间。
参考文献
Redis Lua脚本 实现分布式锁
Redis + lua 分布式锁、分布式限流
Redis分布式锁—SETNX+Lua脚本实现篇