Loading... # redis分布式红锁 redis做分布式锁,就是setnx,成功则表示获得锁,然后设置超时时间,防止客户端挂掉导致死锁,然后添加一个守护线程,在任务执行完之前去刷新超时时间,防止超时时间设置短了导致锁释放。这套方案redisson已经帮我们实现了。 ## RedissonLock分布式锁 添加依赖 ``` <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.3.2</version> </dependency> ``` **单机模式** ``` @Bean(name = "redisson") @Order(1) public Redisson getRedisson(){ Config config = new Config(); config.useSingleServer() .setAddress("192.168.106.99:6379"); singleServerConfig.setPassword(password);//设置密码 return (Redisson) Redisson.create(config); } ``` **集群模式(哨兵)** ``` @Bean(name = "redisson") @Order(1) public Redisson getRedisson(){ Config config = new Config(); config.useSentinelServers() .setMasterName("mymaster") //哨兵配置的组名 .addSentinelAddress("192.168.60.99:26379","192.168.60.99:26380","192.168.60.99:26381")//哨兵地址 .setDatabase(0); return (Redisson) Redisson.create(config); } ``` 使用: ``` @Autowired private Redisson redisson; public void test(){ String lock = "lock"; RLock rLock = redisson.getLock(lock.intern()); rLock.lock(); try { // 具体业务逻辑 } finally { rLock.unlock(); } } ``` 这就是redisson锁的使用,但是这种方案有问题,首先,如果使用一个redis,那么会有单点故障问题,必须要做集群。然而集群环境又会有数据同步问题,比如,客户端向主节点获取锁,主节点还没来得及向从节点同步,就挂了,锁就丢失了。基于这些问题,redis的作者提出了红锁(redlock)的概念。 ## RedissonRedLock分布式红锁 redis的作者提出了红锁的概念,即向多个独立的redis获取锁,他们之间不做主从复制,这个获取锁的操作要有一个超时时间,这个时间应该远小于锁的有效时间,向其中一个获取锁失败,应该立即向下一个获取,包含任何类型的失败,如,redis不可用或者该redis上的锁被其他客户端持有,计算整个获取锁的消耗的时间,如果客户端从大多数节点成功获取了锁(>=N/2+1),并且获取锁消耗的时间不大于锁的有效时间,那么获取锁成功,反之,获取锁失败,如果最终获取锁成功,那么锁的有效时间要重新计算,它等于原来的有效时间减去获取锁消耗的时间,如果最终获取锁失败了(成功获取的节点数小于N/2+1,或者获取锁的时间超过了锁的有效时间),那么客户端立即向redis发送释放锁的操作(lua脚本),释放的过程比较简单,客户端向所有Redis节点发起释放锁的操作,不管这些节点当时在获取锁的时候成功与否。听起来很复杂,但是redis已经帮我们封装好了。 ``` @Bean public RedissonClient redissonRed1(){ Config config = new Config(); config.useSingleServer().setAddress("192.168.106.99:6379").setDatabase(0); return Redisson.create(config); } @Bean public RedissonClient redissonRed2(){ Config config = new Config(); config.useSingleServer().setAddress("192.168.106.99:6380").setDatabase(0); return Redisson.create(config); } @Bean public RedissonClient redissonRed3(){ Config config = new Config(); config.useSingleServer().setAddress("192.168.106.99:6381").setDatabase(0); return Redisson.create(config); } ``` 使用: ``` @Autowired private RedissonClient redissonRed1; @Autowired private RedissonClient redissonRed2; @Autowired private RedissonClient redissonRed3; public void test(){ String lockKey = "lock".intern(); //红锁 RLock rLock1 = redissonRed1.getLock(lockKey); RLock rLock2 = redissonRed2.getLock(lockKey); RLock rLock3 = redissonRed3.getLock(lockKey); RedissonRedLock rLock = new RedissonRedLock(rLock1, rLock2, rLock3); rLock.lock(); try { // 具体业务逻辑 } finally { rLock.unlock(); } } ``` Last modification:June 21st, 2020 at 09:58 am © 允许规范转载