1、基础实现
加锁通过redis的set命令实现:
key:锁名
requestId:锁值,用于解锁
NX:key不存在时才能添加成功,以此来实现锁
EX、expireTime:锁的超时时间
String result = jedis.set(key, requestId, "NX", "EX", expireTime);
解锁先判断锁名key是否存在以及归属自己(通过requestId值判断),若是则删除该key对应的锁
为了实现原子性,通过Lua脚本代码执行
private static final String DEL_SCRIPT =
"if
redis.call('get', KEYS[1]) == ARGV[1]
then
return redis.call('del', KEYS[1])
else
return 0 end
";
jedis.eval(DEL_SCRIPT, Collections.singletonList(key), Collections.singletonList(requestId));
2、如何处理超时情况出现
设置合理的超时时间,但如何才能定义一个合理的超时时间,即使预估了一般情况下业务执行所需耗费的最大时间,也仍然会有其他情况出现,比如网络、GC等。
可以增加看门狗线程(WatchDog)来监控,当剩余时间小于一定大小时,若加锁业务仍未处理完成则将超时时间恢复到原始大小,如此反复直到业务处理完成
Redisson框架提供了该具体实现
3、可重入性
基础实现不支持锁的可重入性,可通过redis的哈希表记录重入次数实现
Redisson框架提供了该具体实现
4、自旋锁
5、锁信息的订阅发布
6、redis单例
以上讨论均基于依赖的是redis单机实例,如果使用redis集群,会有概率出现锁失效的情况出现。
红锁(RedLock)的有效性目前还是有争议的,且性能损坏较大,因此实际使用不多。
7、总结
a、在了解内部实现的基础上使用Redisson框架,不要自己造车轮,总有人想的比你多比你全
b、分布式锁目前不存在100%有效的方案,所以对于重要性非常高的数据,建议在数据端保证数据操作的原子性
本文探讨了基于Redis的分布式锁实现,包括基础的加锁、解锁操作,以及处理超时、可重入性、自旋锁和锁信息的发布订阅。文中提到通过设置看门狗线程来应对超时问题,Redisson框架提供了相应解决方案。同时,指出在Redis集群中可能存在的锁失效问题,以及RedLock的有效性争议。最后,建议在理解底层原理基础上使用成熟框架,并强调分布式锁无法做到100%有效性,对于重要数据应考虑数据端原子性保障。
4085

被折叠的 条评论
为什么被折叠?



