解决多线程消费kafka转存批量数据到mysql,重复数据引起的死锁问题

问题背景

需求中需要消费kafka中的数据,将数据转存到mysql中。为了提高消费效率,采用mysql批量插入,并引入了多线程,
其中批量插入由list保存定量的数据一次性插入实现,由此引发kafka中重复的数据多线程批量插入mysql出现死锁问
题。报错描述是这样:Deadlock found when trying to get lock; try restarting transaction。这是因为
mysql数据表中定义了唯一主键,同时插入了多条相同的数据进入mysql数据表引起的死锁问题。

解决方案

经过漫长的查询资料、思考、编码、测试后,得到一个可靠的解决方案,并亲测有效。问题的原因就是同时插入多条
相同数据,所以解决问题的思路就是在多线程下给数据去重。方法就是定义一个全局的变量List集合uniqueList保存
数据的主键,保证数据的唯一性,因为在多线程下,这个uniqueList使用CopyOnWriteArrayList实现,这里面使用了
分段锁的方式提高了多线程下数据读取的速率。在将新数据放入批量插入mysql的list中之前,都通过uniqueList判断
新数据是否与已经保存的数据有重复情况,重复则丢弃,不重复则放进去。同时为了保证全局的uniqueList不出现
数据量过多,造成oom内存溢出问题,每插入一个批次的数据则将该批次的数据的主键从uniqueList中移除。至此,
该问题可以解决。代码太长不适合粘贴,这里只做思路记录。

注意:在之后的实践中有了新的问题, CopyOnWriteArrayList 确实可以保证数据的线程安全问题,但是它写时复制特性在数据量比较大的时候会出现OOM的问题。这里建议使用 ArrayBlockingQueue 作为代替,同时因为是队列,其长度是定义时就需要设置好,不能灵活长短变化,所以我采用了写入数据量控制,避免出现队列溢出的错误。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值