实现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挺好用的。