缓存密集加载导致数据库崩溃问题

[原创]个人理解,请批判接受,有误请指正。转载请注明出处: https://heyfl.gitee.io/Bug-Log-Optimization/cache-load-database-crash.html


背景

SISP自己基本不存储业务数据,但是每个节点都需要本地缓存了一些网点、员工信息、月结用户信息等基础数据,生产监控发现数据库定期压力飙升,数据库CPU压力到达80+%如图:
优化前.png

用脚趾头分析

  • 从图中可以看出,每天小时飙升一次,明显就是定时任务大批量查询数据库导致的,在SISP系统,也就只有加载缓存可能会导致
  • 找到运维获取慢日志,发现大量的查询语句,如下:
1
2
3
4
5
SELECT DISTINCT nd.division_code AS city_code, nnd.dist_cn_name , nnd.dist_en_name
FROM tm_new_district nd, tm_new_district nnd
WHERE nd.division_code IN(
SELECT DISTINCT t.CITY_CODE FROM tm_department t,tm_district d WHERE t.DIST_CODE = d.DIST_CODE AND t.DELETE_FLG = 0 AND d.DIST_NAME LIKE '%/%'
)AND nnd.dist_code = nd.city_code

因为是单库,数据量也大,单条sql查询耗时近40s,因此,大量查询导致数据库压力飙升

解决

解决手段1:缓存刷新时间分散开,错峰加载缓存

因为是通用方法,这里8分钟内刷新一次的小任务就忽略了。我们对大于8分钟的任务,增加了随机时间间隔,如下代码所示(其中delayPercent = 0.2,表示随机减少时间定时任务0~20%的间隔时间):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 将日期加上一个随机的时间间隔
* @param date 原始日期
* @return 计算后的新日期
*/
private Date scheduleTimeAddRandom(Date date) {
// 获取当前时间戳
long now = System.currentTimeMillis();
// 计算初始时间间隔
long initialDelay = date.getTime() - now;
// 获取当前线程的随机数生成器
ThreadLocalRandom random = ThreadLocalRandom.current();
// 对于间隔超过8分钟的任务,随机减少一部分时间间隔
if (initialDelay * delayPercent > (8 * 60 * 1000 * delayPercent) && initialDelay > 0) {
initialDelay = initialDelay - random.nextLong((long) (initialDelay * delayPercent));
}
// 计算最终的下次执行时间
Date nextExecuteTm = new Date(now + initialDelay);
return nextExecuteTm;
}

解决手段2: 优化慢查询sql

重新梳理业务逻辑,其实我们只是需要城市代码对应的多城市名而已,其在tm_new_district中就有了,只是我们没有从上游上同步到我们数据库罢了。
同步完对应表字段后,完全不需要连接表,用一条简单sql就可以了,新的SQL:

1
SELECT DIST_CODE, DIVISION_CODE, CITY_CODE, dist_cn_name,dist_en_name FROM tm_new_district t WHERE t.division_code IS NOT NULL

新的sql查询耗时只有不到1s,因此,大量查询导致数据库压力飙升的问题得到了解决

上线后优化效果

优化前CPU压力图(单节点):

优化前.png

手段1优化后:

优化后-随机提前20%任务时间.png

结合手段1、手段2,优化后:

优化后2-随机提前20%+慢查询优化(因增加了高频率定时任务,所以总体cpu占用高了)V2.png
优化后2-随机提前20%+慢查询优化---应用服务监控.png

结论

经过优化后,数据库压力得到了很大的缓解,突发峰值也基本消失;应用CPU压力也从原来的15%降低到3%左右,整体系统性能得到了很大的提升。

结语

这次分享了:缓存短时间密集加载sql慢查询(姑且算是吧)的处理。算是很经典的问题了,到处都会遇到,希望能帮助到大家。

作者

神奇宝贝大师

发布于

2022-01-04

更新于

2022-01-05

许可协议

评论