线上ElasticJob堵塞问题排查
[原创]个人理解,请批判接受,有误请指正。转载请注明出处: https://heyfl.gitee.io/Bug-Log-Optimization/elasticJob-bug-fix.html
背景
刚进新公司3天正逢双十一,领导生产补数出问题了,
补数速度不稳定时快时慢
,百万条数据补了好几个小时,之前都是几分钟搞定的,导致通了个宵;
早上我早到公司,领导截了个数据库的图给我,说交给我来看,然后刚通宵完的他就去开会汇报去了。。。我还没来得及熟悉环境,就被扔到了火坑里了,压力山大。。。
具体的过程没记录,这里只能凭回忆记录下了
问题描述
给我的截图大概长这样:
数据库分库号 | 需要补数的运单数量 |
---|---|
分库0 | 12345 |
分库1 | 0 |
分库2 | 0 |
… | *** |
分库31 | 0 |
分库32 | 0 |
分库32 | 5w |
分库33 | 4w |
分库34 | 8w |
… | *** |
分库128 | 8w |
知道的太少,跟同事了解业务,其实补数就是重推数据,把需要重推的单号记入表中,然后通过ElasticJob定时任务消费表中数据,实现重推数据
问题分析
没用过ElasticJob这类定时任务组件,先通过现象分析,发现分库32-128的数据都是好几w条,而且分库0-31的数据都是0,这就很奇怪了;
查看配置sharding-total-count=16,看现象猜测是只有一个分片在跑,且一轮跑16个分片,跑到第二轮;
问题分析
因为实在不熟悉定时任务组件逻辑,还是得去分析源码看原因才好解决问题;
看了下配置
1 | streaming-process=true |
streaming-process=true 代表流式处理;
sharding-total-count=16 代表分片总数;
结合问题,猜测是只有一个分片在消费,且一轮跑16个分片,跑到第二轮;
查看流式计算源码发现流式计算逻辑其实是:
- 各个节点接收任务
- 切分16个分片,当前节点只消费一个分片
- 所有分片处理完后,分发触发下一(16个分片)次的任务
而我们系统对每个分片的处理实际上也是流式的,大致代码如下:
1 | while(fetchData()){ |
fetchData()每次获取200条数据,如果有数据就进行重推,直到结束;
结论
那么问题就很明显了,研发人员把重推任务设置为流式处理,但是每次重推只处理200条数据,导致每个分片处理完后,分发下一轮任务;
但是在第二轮任务因为这某个节点分片数据量很大,导致其他节点早就处理完了,而这个节点的数据迟迟处理不完,任务一直结束不了一直在等待这个分片的完成,消费效率滑坡;
处理方案
- 流式计算加入超时机制,每个分片最多只能处理一段时间,超过后就结束本次任务,分发下一轮任务
- 放弃流式计算,缩短定时任务间隔
这里推荐方案1,不过最终团队选择方案2,实现比较简单。。。
线上ElasticJob堵塞问题排查
https://heyfl.gitee.io/Bug-Log-Optimization/elasticJob-bug-fix.html