Redisson仲裁配置及锁获取时仲裁大小设置的技术咨询
嘿,这个问题问到点子上了——Redis主从切换时的锁一致性问题确实是分布式锁场景里的大坑,稍不注意就会出现脏读脏写!答案是完全可以设置仲裁大小,而且Redisson针对不同的部署架构提供了对应的实现方式,咱们一步步说:
核心配置方案分两种场景
1. 主从架构下:用ReplicatedLock指定仲裁大小
如果你的Redis是主从复制架构(一主多从),Redisson的ReplicatedLock专门解决这种场景下的锁一致性问题。它的核心逻辑是:主节点加锁成功后,必须同步到指定数量的从节点(也就是你要的仲裁大小),才算真正加锁成功。
你可以在初始化Redisson客户端的时候直接配置仲裁大小,代码示例如下:
// 初始化主从架构的Redisson配置 Config config = new Config(); config.useReplicatedServers() .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:6380", "redis://127.0.0.1:6381") .setReplicatedLockQuorumSize(2); // 这里设置仲裁大小为2(假设你有1主2从共3个节点) RedissonClient redisson = Redisson.create(config); RLock lock = redisson.getLock("my_business_lock"); // 加锁时会自动遵循仲裁规则:主节点加锁成功 + 至少1个从节点同步成功,才会返回加锁成功 lock.lock(); try { // 执行你的业务逻辑,不用担心主节点突然挂掉导致锁丢失 } finally { lock.unlock(); }
这里的quorumSize设置为2,意味着总节点数3个的情况下,需要至少2个节点(主+1个从)确认锁存在,才算加锁有效。这样主节点故障切换后,新主节点(原从节点)已经有锁的记录,其他客户端无法重复加锁,自然避免了脏读脏写。
2. 多独立Redis实例下:用RedLock依赖仲裁规则
如果你的Redis是多个独立的实例(不是主从关系),Redisson的RedissonRedLock(红锁)就是基于仲裁机制设计的。它默认的仲裁规则是节点数的一半加1(比如3个实例需要2个加锁成功,5个实例需要3个),这个规则已经能保证分布式场景下的锁安全性。
如果你需要自定义仲裁逻辑,也可以通过继承RedissonRedLock重写相关方法,但一般来说默认规则就足够应对大部分场景了。代码示例:
// 分别初始化多个独立Redis实例的客户端 RedissonClient client1 = Redisson.create(config1); RedissonClient client2 = Redisson.create(config2); RedissonClient client3 = Redisson.create(config3); // 获取每个实例上的锁 RLock lock1 = client1.getLock("my_business_lock"); RLock lock2 = client2.getLock("my_business_lock"); RLock lock3 = client3.getLock("my_business_lock"); // 组合成红锁 RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3); // 加锁时自动遵循默认仲裁规则:至少2个实例加锁成功才算有效 redLock.lock(); try { // 业务逻辑 } finally { redLock.unlock(); }
为什么这样能避免脏读脏写?
核心逻辑很简单:当仲裁条件满足时,意味着足够多的节点已经持久化了锁的状态。哪怕某个主节点突然故障切换,新的主节点(无论是原从节点还是其他独立实例)必然持有锁的信息,不会出现“原主节点锁成功但未同步,新主节点无锁导致其他客户端重复加锁”的情况,从根源上避免了并发写操作或脏读。
备注:内容来源于stack exchange,提问作者Ash

