关于使用分布式锁仍无法解决线程安全问题

最近在项目开发时遇到线程安全问题,简单来说就是通过分布式锁防止多实例入库相同数据失败,不同实例还是会入库相同数据

背景介绍:实例 A、B 接收完全相同的消息,经过加工后入库。为了防止同一份消息入库两次,A、B 采用分布式锁的方式保证同步,其中每条消息都包含唯一 id 字段,以该字段为 Key 建立分布式锁,假如 A 实例抢占到消息1的锁,执行入库并持有锁100秒不释放,在这100秒内当 B 系统扫描到消息1时,无法抢占锁,不执行入库。每条消息的入库都会封装为任务在线程池中执行,所以抢锁失败后不会二次入库

理想状态是每条消息只入库一次,然而在实现运行过程中,还是出现了大量重复入库的数据,并且这部分数据主要集中在业务高峰期后

导致这种情况的主要原因在于无法保证 A、B 两实例总是能在100秒内处理相同的数据,比如 A 实例入库完消息 a 后101秒 B 实例才扫描到消息 a,此时锁已经自然释放,因此 B 实例又执行了一次入库

上面是导致问题的实际原因,具体根本原因如下:

  1. 整体架构不好,应该从上游进行业务分流,A、B 两实例处理不同的消息,否则无法做到水平扩展
  2. A、B 两实例线程池工作线程配置过少,大量的消息都积压在消息队列中,数据库性能完全没有充分发挥(系统中配置单实最多例只有10个线程)
  3. 两台实例性能不同,而且抢到锁的实例执行入库,线程池中后续任务来不及处理,而另一个实例由于抢不到锁,快速向后执行,随着业务量的增大,两实例之间执行消息的差度越来越多,最后极有可能超过100秒

解决方案:

  1. 优化线程池,提高线程池工作线程的数量,充分利用数据库性能
  2. 增加锁失效时间,这个值可以根据业务量设置,一般业务量越大,锁失效的时间越长越安全
  3. 整体架构优化,上游分流,下游不同实例处理不同消息,同时入库

实际以上实例中,分布式锁的使用方式也有问题,分布式锁主要用于多实例同时访问相同数据时的线程安全问题,而上面实例是不能同时访问的,这点大家知道就好

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值