12 月31 日返利系统问题复盘
针对 12 月31 日返利系统问题复盘如下:
问题一
12 月 31号 返利系统费用单未及时传送结算,导致结算无法及时计算,导致后续流程无法进行。。
问题出现及处理过程:
12 月 31 号,下午 5 点半左右业务人员反映有两百多万个费用明细已审核,但未收取。经查询,返利已审核后已经发送结算系统,然后跟结算收取后已经推送 MQ 给返利,此时开始排查接收结算通知的 MQ 部分,发现大量费用单明细重复消费问题(约有 60 w 明细重复消费),进一步查看每次消费 10 条明细消息,存在不少处理时间超过 1 min 的(原消费端返回 ack 确认给 MQ server 的最大超时等待时间为 30s)从而造成了 MQ Server 未收到 ack 确认,导致重复发送,形成恶性循环。当时 18:05 左右开始修改 MQ ack timeout 时间为 5min,先确保不会发生大量重复发送问题。
操作步骤:关闭导入任务,kill 计算任务,k8s 重新拉起服务(在这个过程中 2020-12-31 18:08:04 业务人员恰好正在进行费用单批量审核,这也是后面部分费用明细未进入 fee_send 表的原因)。
改完配置,重启服务之后,查看日志,发现过了大概 1 min 左右,重复消费的消息基本不再出现了,开始处理正常消费了,此时处理的消息费用单和退补单都有,更新处理时间 50~60 ms)
19:36 业务人员反映还是未收到费用单已收取,当时怀疑是消息量多大,重启之后先是进行重复消息的消费,排在前面的传过来的大部分又是退补单,所以费用单应该是排在后面的,估计还要处理一会儿。
当时跟结算确认了一下,一共推送了大约有 50w 个消息 ,对应明细个数为 500w。消费端此时处理了大约 100w 左右的明细。
晚上 21:15 左右大约处理了 210w 明细消息。
21:05 到 10:10 左右消费了 15 w 消息,对应明细大约 150w,到 10:10 左右一共消费了大约 36w 条消息,对应明细约 360w 条,原以为此时以现在的速度到 12 点之前剩下的 150w 左右明细能消费完,但是后来又慢了下来,
11 点多加了四台机器,一共 10 台机器发现处理速度时快时慢(后面排查,快的原因是因为部分是费用单对应的明细较少,还有一部分是退补单明细少的部分,慢的原因是退补单明细多的部分),
凌晨 12 点多,排查出来可能是因为在 update 退补单明细的收取状态的时候没有加联合索引的原因导致的。加上联合索引后,到 12:40 左右全部消费完毕。
后来仔细分析后,整个消费过程中处理快的原因是因为费用单对应的明细较少,update 操作根据 费用单号 headNo 单值索引独占锁锁的行数较少,所以费用单号和退补单号对应的明细较少的 update 就比较快,相反明细较多的,每次 update 更新数据库行锁锁的行数就比较多,这就是造成消费速度慢的根本原因。
以上就是 2020 年 12 月 31 号年度收官出现 MQ queue 堵的整个问题的经过。
问题二
1 月 2 号发现返利传给结算的数据缺失。
问题发生的原因及处理过程:
发生原因:12 月 31 号下午六点左右修改 MQ 配置后重启服务时,已经确定关系费用单导入入口,但是恰巧财务此时正在批量审核费用单,批量审核费用单主要涉及到两个操作。
第一步,更新 fee_head 表状态为“已审核”。
第二步,将已审核的费用单对应的明细组装数据后异步插入到 fee_send 表。
第三步:定时任务每隔 15 分钟将 fee_send 表中已审核的费用单明细传给结算。
发生数据不一致的根本原因是,在第二步中,插入到 fee_send 表操作是异步的。
问题处理
1 月 2 号将 12 月 31 号重启服务过程中正在发生批量审核的涉及到未传送到结算系统的 29425 条费用明细临时写代码,将所有缺失明细全部补推到结算系统。
以上就是元旦返利系统出现的问题,以及处理方法。
对于以上问题,返利在接下来如何避免以上问题的解决方案:
1.消费已收取的退补和费用问题的根本原因已经找到,现已对所有涉及到的费用单明细和退补单明细加上联合索引,彻底解决了消费慢的问题。
2.对于系统突然 crash 或重启可能会导致的审核费用单和退补单插入 fee_send 表数据丢失的部分,由于费用单和退补单涉及到的明细可能比较多,所以不能采取同步的方式插入(性能较差,开始采用异步的方式也是为了避免性能的问题)。