基于Redission的可重试锁
实现Redis的分布式锁,除了自己基于原生API来实现之外,还可以使用开源框架:Redission
Redisson是一个企业级的开源Redis Client,也提供了分布式锁的支持。
我们只需要通过它的API中的trylock和unlock即可完成分布式锁,他帮我们考虑了很多细节:
1:redisson所有指令都通过lua脚本执行,redis支持lua脚本原子性执行
2:redisson设置一个key的默认过期时间为30s,如果某个客户端持有一个锁超过了30s怎么办? redisson中有一个watchdog的概念,翻译过来就是看门狗,它会在你获取锁之后,每隔10秒帮你把key的超时时间设为30s 这样的话,就算一直持有锁也不会出现key过期了,其他线程获取到锁的问题了。
3:redisson的“看门狗”逻辑保证了没有死锁发生。 (如果机器宕机了,看门狗也就没了。此时就不会延长key的过期时间,到了30s之后就会自动过期了,其他线程可以获取到锁)
实例代码:
基于Redission的可重试锁
/** * @author: AngJie * @create: 2022-07-26 14:41 **/ @RestController @RequestMapping("/redisTest") public class RedisTestController { @Autowired private RedisTemplate redisTemplate; @Autowired private Redisson redisson; private final static String LOCK_KEY = "distributedLock"; //基于Redission的可重试锁 @GetMapping("/Retrievable") public void testRetrievableLock() { /*获取对应的key的锁*/ RLock lock = redisson.getLock(LOCK_KEY); // 内部包含 重试机制,通过Redis的发布订阅者模式来实现 /* 参数一:最长等待时间,超时则不再等待 * 参数二:锁超时释放时间 * 参数三:时间单位 */ boolean hasLok = false; try { hasLok = lock.tryLock(6, 20, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } if (hasLok) { try { redisTemplate.opsForValue().increment("TEST"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("Lock Released"); } } else { System.out.println("Can not get lock"); } } }
压测:
利用Jemeter进行10秒钟每秒500并发量的测试。
结论:
Redission挺好用的。