一、背景
在sit环境中,测试批量上传500个网元进行批量激活,突然发现激活任务执行失败,而且系统其他功能接口响应缓慢,系统几乎卡死,服务器OOM。
二、问题分析
分析代码发现,此功能激活子任务把Redis的任务信息全部查询出来,然后放入Redis中,这500个子任务大概任务信息数据量达到37W+。直接导致Redis内存占用率过高,服务器OOM。
三、解决方案
针对修复激活子任务场景,先删除记录,再发送MQ消息,避免重复消费校验住。
旧代码如下,其中entries(statusRedisKey)会将statusRedisKey的所有信息全部查出,查询出的数据量很大!
Map<String,TaskVo> taskMap = RedisUtils.getRedisOperator().getRedisTemplate().opsForHash().entries(statusRedisKey);
// 然后执行RedisUtils.getRedisOperator().getRedisTemplate().opsForHash().put(statusRedisKey,taskVos)
优化后代码
Map<String,TaskVo> taskMap = RedisUtils.getRedisOperator().getRedisTemplate().opsForHash().get(statusRedisKey);
//然后执行put
entries方法会查询所有数据,当数据量超大时候,存入Redis时候,再进行其它业务操作,会引发OOM。
四、大Key的清理
1:低峰期删除:选择业务流量低的时期清理缓存(无法彻底解决)。
2:分批定时定量清理:一次删除一部分,防止一次性删除大批量数据导致阻塞。
3:异步删除:用unlink代替del删除,只是将键与键空间断开连接,实际的删除将稍后异步进行,以非阻塞的方式,逐步的清理插入的key,不阻塞主线程。