一个风控计算负载过高到mysql主从拆分暴露的各种设计复杂性问题以及解决方法总结

时间:2021-08-12 15:00:05

在很多系统(包括金融类和非金融类)中,其实有大量的系统在很长的一段时间内(具体多长时间视业务的成功与否而定)都是混合型系统,也就是同时具有OLTP+OLAP的业务。我们说任何形式的存在在特定阶段都是合理的,这无可厚非,但是对于明知会发生但仅仅只是时间问题的那些问题,如果不吸取以前的经验教训,仅仅是为了快速上线而阉割再阉割,事后补救的成本必定是高昂而且痛苦的。在我们最近的这一次因为实时风控计算导致关键交易系统负载过高而不得不拆分的调整中,纠正和修复了很多原先的设计、实现以及流程上存在问题。

首先,在第一天mysql库拆分后,出现的第一个问题是很多的业务表并没有同步到从库,大量的slave key not found, key duplicate,经检查升级脚本,发现很多地方写死了库名,db_XXX.table_XXX,db_XXX.sp_XXX。一直以来,我们很多开发都知道,其实现在系统耦合性很强,但是自欺欺人的假设数据库已经逻辑上拆分为不同的schema,所以我们是完全可以独立部署的。

其次,行情作为时效性很强、每天会产生大量临时但并不需要存储的数据,明智出事只是时间的问题,我们还是将其存储在了innodb表中(主要还是为了省事),每秒数千条,导致iowait极高、MQ服务器时常盘中出现大量积压,进而导致交易客户端的实施盈亏偏差很大,拖了几个月开发之间均以米有时间为理由,笔者最终改了rpc框架在应用层进行批处理,并在连接级别将sql bin log禁用了,虽然之后行情不在成为领导的关注点。但在主从中,备库行情没有了,同时在批量入库时因为采用了load infile,临时表是diy创建的,使得还出现了table not found的异常。仍然有些地方是人工插入和修改行情记录的,于是slave key not found, key duplicate又出现了。最后,再次修改行情入库的逻辑,行情相关表主、从库同时写。该问题才得以彻底解决。在计划中,后续逻辑会进一步前移,使得不需要再持久化。

第三,我们有很多的存储过程(还是因为历史原因),和第一点一样的方式进行了处理。

第四,在主从的使用上,为了保证代码规范的一致性,我们采用了有些表rewrite-db处理,有些没有rewrite-db处理,一开始使用%通配处理,后来发现还有很多自动备份的表,时常出现table not found, table already exist的异常,最后,不得不要求开发列出完整的清单,此问题才算告一阶段,至今未出现其他问题。但是事后又出现了了一个问题,有些不在列表中的表需要同步,于是就出现备库没有同步过去的情况,这使得每次升级的时候知道有没有要同步的新增表,如果有的话需要对应的修改replicate-wild-do-table。于是,开发、测试、运维各自都不愿意干这事情,使得笔者不得不找个自动化的机制自动进行同步。

原先和最后的系统结构变化,等到后续有时间了在专门整理。

在上述问题的处理过程中,麻烦的不是如何解决,而是每次只要问题类似,出错的记录不同,都不得不一条条记录找出来,跟开发沟通,开发才得以调整,并最终反向慢慢在处理问题的过程中增加和订下各种规则,出了一个公司文化,明显的失误群发一个红包,并推广到开发、测试、运维所有人员,没有想到的是,两次之后,不少开发主动发起了红包。

很长一段时间,笔者发现,问题并不是各同学不愿意调整和优化改进,而不是一直以来他们发现每个人说的都不一样,而且都没有很好地解决他们的问题,久而久之,他们慢慢的就免疫了,不随便相信其他同学说的话,运维、开发各自不信任,自己玩自己的,结果留下了这风格迥异的现状。