数据库QPS调优,好像也没那么难
背景
DBA提示近期凌晨mongo数据库集群QPS指标告警(具体指标为从每天凌晨1点到6点的QPS维持在1.4w-1.5w)急需要排查解决,否则很有因QPS持续过高造成集群产生死锁和脑裂进而导致集群宕机风险。
分析
从DBA给过来的具体的各项指标来看,造成数据库QPS居高不下的原因主要是在凌晨1点有两个大表在同时写入。经排查,是大数据组每天凌晨会触发定时任务,通过kafka做全量数据投递,单独的kafka消费项目通过消费kafka里的全量数据,入库,做save操作,实现大数据量的T+1 日更新。其中两个大表的的数据量平均一天7000w和4000w。
解决
从数据源头层面
增加业务类型过滤,代码逻辑里面只消费指定业务类型的数据。
错峰投递数据,大数据组凌晨1点开始一个定时投递任务,凌晨3点开始另外一个定时投递任务。
从数据消费层面
修改kafka的max.poll.records属性值,从原来的100降到20,面对同一批待消费的数据,通过减小单次批量获取的数量,来提升批量获取的次数,进而增加数据传输的网络消耗,延长整体消费时间,降低数据库平均QPS。
从数据限流层面
借助hutool的ThreadUtil在各个需要消费的Topic里面增加一个限流工具,比如可以指定在持续消费某Topic的数量达到某一阈值时,手动让线程sleep多少秒。注意不能超过kafka的max.poll.interval.ms设置的时间(当时设置的是600s),不然会造成kafka的rebalance,代码如下:
/**
* 限流
*
* @param atomicLong
* @param sleepMills
* @param limitSize
* @param addSize
*/
public static void currentLimit(AtomicLong atomicLong, long sleepMills, int limitSize, int addSize) {
if (atomicLong.get() >= limitSize) {
ThreadUtil.safeSleep(sleepMills);
atomicLong.set(0);
}
atomicLong.addAndGet(addSize);
}
优化后效果
数据在凌晨1点开始错峰投递,凌晨5点前可以消费完。
QPS 下降至1k-2k,是优化前QPS的10%,优化效果明显。
思考
在弄清楚数据流向的来龙去脉之后,其实这类问题运用一些简单的理性思维很好解决。
就像初中时的一道物理题一样
问:减少噪音的三种方法是什么?
答:在声源处控制,在噪声传播途中控制,在人耳处减弱噪声。
转载自:https://juejin.cn/post/7241101553712218171