大数据导入Mysql踩坑

涉及技术简述

微服务架构,k8s部署管理,大数据导入数据库的功能涉及两个服务,一个负责csv文件的定时读取,一个负责文本的处理及入库。
读取服务会将文件内容按OLT粒度涉及的硬件消息,分为约5000条5~10kb的消息发送到kafka指定Topic的同一个分片,此项目分区pattern只设置了2个。均匀分发消息。

处理入库服务则是从消息队列读取消息。然后线程池并发处理。

踩坑及处理

我们的目的是,尽量快速处理约1.5GB的csv文件,具体到数据库的record约1000w左右,最开始预期是15分钟内处理完毕,以下是踩坑:

  1. 入库速度非常缓慢,约2个小时;
    原因:消息队列消息提交偏移量的方法是手动提交,每条消息1执行,提交偏移量阻塞导致。
    解决方案:最先考虑的是采用并发消费,但因为数据要求有顺序性,改为并发消费之后,整个功能就坏掉了。最后采用的是按整个OLT的消息,约5000条,进行一次偏移量提交
    效果:入库由120分钟优化到60分钟。
  2. 数据库死锁频繁;
    原因:间隙锁及where条件未能走索引导致行锁升级为表所
    解决方案:排查了所有的SQL,where条件是有索引的,新增了where条件减小了行锁粒度,并更改了默认的数据库级别,由rr->rc。数据库死锁频率减小,但是仍然存在。
    效果:60分钟到30分钟
  3. 线程池数据不安全;
    原因:数据不安全
    这个是剩余死锁问题的排查,查看数据库的最近死锁记录,发现两个不同表也会死锁,非常奇怪。
    最开始发现消息队列消息似乎是重复消费了,但最后确认是因为线程池里的数据不安全导致的类似现象。
    线程池提交的任务里,有调用一个函数,函数内部会指定一块内存地址保存处理后的数据,处理完毕后返回该地址给调用线程,但是问题就出现在这里,我的排查结果是,该函数返回的地址在多线程情况下,会导致线程不安全的问题。虽然改完之后死锁完全消失,但是最后也没能确认具体原理,待补充。
    效果:速率没有更有效提升

后记

这个功能的优化持续了约10个工作日之久,期间涉及到的技术都是我之前没涉及的。在此列出
kafka:SpringBoot集成的kafkaTemplate、@Listener,分区pattern,并发消费,偏移量提交,kafka管理工具
线程池: 函数涉及的数据安全问题
数据库: 间隙锁,除select以外的命令未走索引导致的行锁与表锁,如何查看数据库死锁日志
k8s: kubectl的常用命令,docker命令,k8s基础概念

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐