【未限制消息消费导致数据库CPU告警问题排查及解决方案】
一、背景
某天下午,上游系统同一时间突然下了三个大合同数据,平均每个合同数据实例在6万以上的量级,短短几分钟内瞬间有20万左右的流量涌入系统。
而在正常情况下,系统1天处理的流量也不过2千量级,当时数据库指标监控告警,数据库会话直线上升,CPU毛刺增多,达到了80%。
二、排查措施
1:数据管家平台查看慢SQL执行情况,并分析出现慢SQL原因
2:查看消息平台的业务报错记录日志,根据报错来看,数据库无法获取连接,标识当时数据库的处理能力已经达到上线,无法同时处理这么多会话
3:分析docker运行情况,无大的波动,基于此,定位到影响业务的瓶颈在数据库
三、整改措施
大批量的信息消费,如果通过升级数据库规格,增大连接数等手段虽然短时间内可以解决问题,但是增加了机器成本,无法彻底解决问题。
1:控制事务的粒度
在进行事务处理时候,尽量减少事务的范围,避免长时间占用数据库连接。可以将多个大的数据库操作拆分成介个小事务或者无事务,这样就可以释放更多的数据连接,提升并发处理能力。评估了核销这块逻辑事务影响不大,最终改成无事务操作数据库。
2:优化代码结构,减少数据库交互
优化代码,优化SQL等手段,比如循环单个处理改成批处理等等。
3:削峰填谷(主要措施)
1)通过设置消息消费配置降低服务消息速度
目前交付单系统服务生产环境部署8台服务器,每台机器配置的消费线程是4,从机器运行指标情况来看,docker无压力,可以分析得出服务消费消息速度过快,数据库处理能力跟不上。比如我们定义consumer参数为
//拉取批次消息个数,保持不变
setPullBatchSize(32);
//缓存消息个数,指单个queue,默认1个topic对应8个queue,1个消费者最大会缓存8000条,保持不变
setPullThresholdForQueue(1000)
//消费线程最小数,可以降低配置到4
setConsumerThreadMin(8)
2)使用任务Job进行削峰
上游OMS系统瞬时下发的消息,统一先落入集成的数据库表,落入表之后不立即触发世间处理,而是由1个ischeduler定时调度任务,按照恒定的速率取固定size数量数据进行捞取进行处理。这样保证上游无论
瞬时数据多大的并发,我们数据库都不会因为压力过大而丢失数据