Redis-分布式锁
8.如何基于Redis实现分布式锁?
- 在Redis中,通过
SETNX
来保证互斥,SETNX
(SET If Not Exist
),如果key不存在直接设置key的值,如果key存在,SETNX啥也不做。 - 释放锁就是使用DEL命令删除对应的Key即可,为了防止误删其它的锁,一般需要通过Lua脚本来保证删除操作的原子性。释放锁时先比较
vaule
值是否相等,如果相等再释放。但是这样实现的分布式锁存在一个问题,如果删除锁的逻辑突然挂掉,那么就锁就会一直存在。我们可以通过EX
对锁设置一个过期时间,但是这个时间不好控制,如果操作共享资源的时间大于锁的过期时间,就会导致锁提前释放。 Redission
实现的分布式锁可以进行自动续期,它的原理就是基于看门狗
实现的,看门狗是专门用来监控和续期锁的。看门狗给锁的默认释放时间是30
秒,每过1/3
的释放时间就会自动执行续期操作。看门狗在续期之前还会先判断是否需要续期,如果锁指定了过期时间,就不会用到看门狗机制。看门狗的底层是通过Lua
脚本和SETNX
实现的,Lua
脚本就是为了保证操作的原子性。
9.如何实防止重复下单?
当用户下单的时候,可以通过当前用户唯一的key调用setnx来存储
,哪怕调用多次也只能调用成功一次。唯一的key使用:用户token+商品的url和重复提交的key,保证当前用户当前商品重复下单操作只能提交一次,其他通过setNX保存失败的都忽略掉。
10.你了解可重入锁吗?
可重入锁就是在一个线程中可以多次获取同一把锁,无需重新获取锁。Reids实现的分布式锁是不可以重入的,但是Redission实现的分布式锁是可以重入的。可重入锁的实现思路是为每个锁设置一个线程ID和重入次数
,当重入次数大于0时,需要判断该占有锁的线程和请求获取锁的线程是否为同一个,如果是同一个就将重入次数加1。
11.Redis如何解决集群下分布式锁的可靠性?
Redis集群下,数据同步到其它节点是异步的。如果在Redis主节点获取锁之后,数据还没有同步到其它节点,此时主节点宕机了。选取的新的主节点就会再次获取锁,这就不满足锁的互斥性了。解决方案就是使用红锁
,红锁的原理是不能在一个实例上加锁,要在一半以上的实例上加锁
。这样主节点宕机之后,就不能在其它节点上加锁了,红锁的实现复杂,性能很差。