一、问题描述
内存使用率过高.png内存使用率过高,一直是97~98%的,我们的redis的配置是4G集群版(8节点)。
二、问题原因
程序里在写入key的时候,忘记写入ttl值,导致一直停留在内存中。
另外,它是一个大key,按天存储所有的房间列表。
代码示例
public void addTodayActiveRoom(String roomId) {
String key = redisConfig.getKeyPrefix() + Redis.ENTIRETY_RECORD_TODAY_ACTIVE_ROOMS + getToday();
redisTemplate.opsForSet().add(key, roomId);
// 这里缺少对key的ttl赋值
}
修改后的代码:
public void addTodayActiveRoom(String roomId) {
String key = redisConfig.getKeyPrefix() + Redis.ENTIRETY_RECORD_TODAY_ACTIVE_ROOMS + getToday();
redisTemplate.opsForSet().add(key, roomId);
expireRedisKey(roomId);
}
解决办法
经统计,redis-cli keys "channel_entiretyRecordActiveRooms:*" 的key值361个,也就是说长期以来(几年下来),这些Key都是存在的,永不会过期删除。
而redis实例总共有31万多个key,认为即使删除了这些几百个key,无关伤痛,不能对内存有任何缓解。
//手动删除历史的key
redis-cli keys "ykt_channel_entiretyRecordActiveRooms:*" |xargs redis-cli del
执行后的一分钟内,便明显看到了效果,内存一直直降,从97%到48%。
内存使用率降低至48%.png三、总结
- redis的list等集合,在业务量大的时候,很容易成为"大key"。再加上没有设置过期时间,就是大号的僵尸了。其危害可真大!
- 总结本问题,希望能对“言必称redis”的开发同事有所警戒。因为redis一般没有只读的权限,所以开发和测试很难发现这种坑。而传统的数据库,不太会发生这种奇葩问题。
网友评论