Redis主从架构的分布式锁失效场景是啥?如何解决?
面试题~
1 个回答
遇见错的人会消耗你,遇见对的人会治愈你。java小王子### 问题描述 在Redis主从架构中,写入都是写入主Redis实例,主实例会向从实例同步key。 一个业务线程A通过向主Redis实例中写入来实现加分布式锁,加锁后开始执行业务代码。这时如果主Redis实例挂掉了,会选举出一个从Redis实例成为主的,如果刚刚加锁的key还没有来得及同步到从Redis中,那么选举出来的新的主Redis实例中就没有这个key,这个时候业务线程B就能加锁来获取分布式锁,执行业务代码了,而这个时候A还没有执行结束,所以就会出现并发安全问题,这就是Redis主从架构的分布式锁失效问题。  ### 解决方案 #### 1.使用Zookeeper代替Redis解决分布式锁失效问题 Zookeeper(以后简称ZK)也是一种k-v形式的存储中间件,只是它的内部结构是树形的,在ZK的集群里也有主从的概念,主结点叫Leader,从结点叫Follower,如果使用ZK就能解决这种主从同步引起的分布式锁失效问题。 这是因为CAP理论说明,一致性、可用性和分区容错性最多只能保持三个中的两个(其中分区容错性一定要保持),Redis集群倾向AP(也就是更关注可用性),ZP集群则倾向CP(也就是更关注一致性)。 在向Redis集群里的主结点写入数据时,写入主节点就立刻告诉客户端写入成功。而在向ZK的主结点写入数据时,并不是立刻告诉客户端写入成功,而是先同步给从结点,至少半数的节点同步成功才能返回“写入成功”给客户端。 这个时候如果ZK的主节点挂了,ZK的ZAB分布式一致性协议能保证一定是数据同步完成的结点被选举为主节点,所以就不会发生分布式锁的失效问题。 #### 2.使用RedLock解决分布式锁失效问题 如果不改用ZK,就是要用Redis来解决主从架构的分布式锁失效问题,那么可以使用RedLock,RedLock底层逻辑和ZK很类似。 首先要有多个(最好是奇数个)对等的(没有主从关系)Redis结点。当进行加锁时(比如是用SETNX命令),则这个设置key-value的命令会发给每个Redis结点执行,当且仅当客户端收到超过半数的结点写成功的消息时,才认为加锁成功,才开始执行后面的业务代码。  下图中,Client 1向Redis 1/2/3三个结点去写key-value,假设当前处在Redis 1和Redis 2写入成功了,Redis 3还没有写入成功的状态,这个时候Client 1就已经认为加锁成功了,实际上已经可以执行业务代码了。 此时,假设有一个Redis结点挂了(最坏的情况就是已经写入了key的一个结点挂了,如下图所示Redis 1挂了),这个时候假设Client 2也要尝试加锁,此时Redis 2由于已经被Client 1写过了,没法写入成功,但是Redis 3可以写入成功。此时只有1个结点能写入成功,所以认为加锁不成功,这样Client 2就不会开始错误的执行业务代码,也就不会出现并发安全问题。  RedLock目前还有一些争议,所以很多时候可能不会用这种解决方案。下面是老师上课时展示的一块用Redisson实现RedLock的伪代码。在使用的时候,大体就是对不同的Redis实例,用Redisson获取RLock对象,然后用这些RLock对象来构造RedissonRedLock对象,然后用它来实现加锁解锁的逻辑即可。 发布于 2022-12-29 23:44 •IP属地 青海举报评论收藏
公众号进入网站体验更佳

