SpringBoot使用RedisTemplate+Lua脚本实现Redis分布式锁
问题:定时任务部署在多台Tomcat上,因此到达指定的定时时间时,多台机器上的定时器可能会同时启动,造成重复数据或者程序异常等问题。
1 | //发送消息,不能重复发送 |
使用分布式锁来控制,谁抢到了锁就让谁执行。
一、基于Redis实现分布式锁
1 | package cn.pconline.pcloud.base.util; |
使用方法:
1 | @Scheduled(cron = "0 0/15 * * * ? ") |
二、分布式锁的要求
- 互斥性。在任意时刻,只有一个客户端能持有锁。
- 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
- 具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
- 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
三、存在的问题
注意!!!! 该加锁方法仅针对单实例 Redis 可实现分布式加锁,或者使用场景少的业务。
原因对于 Redis 集群会有一定几率出现问题
例如:当进程1对master节点写入了锁,此时master节点宕机,slave节点提升为master而刚刚写入master的锁还未同步,此时进程2也将能够获取锁成功,此时必然会导致数据不同步问题。还有另一个问题即: key 超时之后业务并没有执行完毕但却自动释放锁了,这样就会导致并发问题。
如果需要更加健壮的Redis集群分布式锁,推荐使用Redisson。