关于redis分布式锁的一些思考,离开场景谈架构就是耍流氓

Redis 分布式锁

redis分布式锁 ,我想大家都经常使用。在面试的时候,也经常被问到。那么,你是否真的认真思考过,redis分布式锁的优势和劣势呢,今天,正好改造一个单点的定时任务系统,就记录一下自己的思考吧!

单点应用要升级分布书应用

同事为了快速和供应商对接,在短时间内实现了一个定时推送的系统,用的spring中的定时任务Scheduled,快速实现了,并且应用单点部署到生产服务器上。
我接到手里,就看见了两个问题:

  • 单点问题,如果服务器挂了,那么整个对外提供的服务就挂了,将出现P0级别的BUG,对业务影响巨大。
  • 如果,升级分布式系统,那么原来的定时任务,就会多点同时触发。
  • 如果,用了redis中的setNX分布式锁,能解决多点触发的问题。但是,也会引申出很多场景问题。

那么,下面,一步一步深入解决各种问题。

NO1.升级分布式系统

这个问题,很好解决,在原来的基础上,再申请几台节点就可以了,最好是奇数太节点。

NO2.定时任务问题

定时任务,从单点系统升级到分布式系统,就会出现所有节点同时触发定时任务的问题。

解决方案:使用分布式锁

分布式锁的实现方式有两种,一种是Redis分布式锁,一种是zookeeper分布式锁,怎么选型呢?

技术选型

Redis分布式锁
1.性能好
2.实现简单
3.有短暂的死锁
zookeeper分布式锁
1.性能好(相对Redis差一点)
2.实现复杂
3.不会出现死锁

最终,选择Redis实现分布式锁。

Redis分布式锁setNX

常规实现,获取分布式锁,分为两个步骤:
1.setNX获取锁
2.设置过期时间

思考:执行业务到一半的时候,业务出现异常,怎么办?

业务执行到一半,程序出现异常,这个要处理一下几个问题:
1.异常处理,既然,程序出现问题,就要捕获,处理异常。
2.获取到的锁,需要释放,不能因为程序的异常导致锁不释放。
所以,捕获异常以后,去释放掉锁

思考:业务执行到一半,锁过期了,怎么办?

出现这个问题,说明当初没有考虑到程序执行的整体时间。
那么,过期时间怎么设定才合理呢?通过多次测试程序的总体运行时间,取最长的,再加上3秒钟。

思考:业务执行完了,锁还有好久过期,怎么办?

这个很简单,我们在程序中加入finally,在程序运行完成的时候,去释放锁,就可以了

思考:业务执行的时候,当前执行业务的服务器当机了,怎么办?

这个没办法处理,服务器当机了,只能重启。但是,我们获取的锁,是没有办法释放的,只能等到自动过期。这就是所谓的短暂的死锁。

思考:key相同,value不相同,设置过期时间,为什么要这样实现?

第一个:过期时间保证锁在时间内有效,过期能自动释放
第二个:key相同,很好理解,只有在同一时刻,有且仅有一个持有锁
第三个:为什么设置value不相同呢?我还在想,也许是有极限的时候,两个程序同时持有锁吧,但是,这样就违背了分布式锁只能有一个持有者啊!

思考:从步骤看,这个操作不是原子操作,不是原子操作,有原子操作的API吗?

有的,set key value nxxx exxx timeout

总结:

  • 使用原子操作获取锁
  • 设置过期时间,保障锁一定会释放
  • 处理业务异常,有异常,释放锁
  • 用到锁的地方,记得加finally,执行完业务释放锁
发布了78 篇原创文章 · 获赞 29 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/lvhonglei1987/article/details/104616370