关于数据雪崩的问题复盘

这周遇到一个数据雪崩的问题,从周四开始就没安稳的休息过,
感觉有必要记录一下.

周三的时候发布了一个版本,
里面主要包含两个业务,
1、调整旧接口逻辑
2、接入新的kafka服务,但是这个kafka不是直接对接,因为openresty不支持密码校验,所以用的另外一个golang写的程序去对接kafka

发布完之后,日志里面没什么错误,但是第二天起床,一堆告警,很多任务都失败了,而且即使算出来的数据内容很多也不正确.

一开始我并没觉得是自己发布代码的问题, 以为是前端报过来的数据有问题,所以导致统计失败,所以没有在意, 粗略的统计了一个异常数据,也就几万条, 想了一下感觉没什么,就开始改统计任务,来兼容这种脏数据.

任务搞完之后,我开始排查脏数据出现在哪台机器上,因为如果是前端报过来的,应该会比较好定位, 然后我惊喜的发现错误内容比较集中在某一台机器上的某一个进程里,这里完全被带歪了,我排查了很久,然后选择了重启,以为这样就能解决问题.

但是周五的时候,这种脏数据出现了十几万条,然后集群每台机器都有脏数据,并且不是固定出现了,此时的我开始警觉

接着是周六,脏数据出现了几十万条,我瞬间就炸了

然后我开始仔细思考到底是哪里有问题,突然我想到,可以对每台机器上的某些固定位置的数据进行校验,如果异常,就统计并展示出来

结果是,对每台机器的数据校验之后,所有的机器都有脏数据,我开始怀疑是自己发布的版本有问题了

然后回滚,一切数据就正常了

那么问题来了,是哪个逻辑导致的问题
我开始复盘代码

有两个地方引起了我的注意,一个是上报新的kafka-golang服务的时候会经常超时,另外一个是写本地文件数据的同时,会上报一次kafka-golang服务, 问题应该就出在这里了

openresty是一个协程框架,每次网络io的时候都会切出上下文,等下一次回包的时候,重新恢复现场,执行下一步逻辑

然后,我每次写完文件,并没有执行flush操作,
但是之前这个写文件的函数里面也有写kafka服务, 可能是之前写kafka都是用openresty的开源组件,并且是异步写的, 没有网络io, 所以写本地文件一直没有乱序,这一次用的是同步上报,所以写文件的时候,开始乱序了

问题已经定位到了

我在写本地文件的同时,执行了写kafka-A服务,和kafka-golang服务, kafka-A服务是异步写的, kafka-golang服务是同步写的(有协程切换), 就是因为这一个协程切换,把我之前的写文件没有flush的bug给触发了, 导致写到文件的时候开始乱序了

接下来就很好解决了, 我把kafka相关的逻辑全部迁移走, 然后保证写文件的时候是原子的,没有协程切换,整个数据结果就ok了