定时清理Redis妙招不断(怎么定时清理redis)

Redis作为高性能的缓存、消息中间件,被广泛应用在网站、异步任务、队列中间件等分布式场景。尤其是在使用无状态技术(如:React、SpringCloud)实现微服务架构时,Redis用作Session载体,也更加势不可挡。

我们都知道Redis有实时剔除存储池中过时(expired)的key的功能,但由于这种操作有可能会进行大量的内存操作,从而影响Redis服务性能,所以Redis默认是不会定时剔除key的。将过时key全部清理走,这也就是定时清理这件事情的出发点。

那么我们有哪些妙招能够定时吊销过期key呢?

1. 使用定时任务实现,用代码定时扫描Redis key,然后把过期的key进行删除;

// 每隔5分钟轮训一次已经失效的keys,并定时清理
// 说明:
// - ONE_MIN = 60 一分钟的秒数
// - MAX_KEYS_NUM = 1000 每次最多拿1000条返回,太多可能会报内存溢出的错
// - TIMEOUT_THRESOLD = 3600 代表一小时的秒数,拿出过期的keys,让在一小时内已经失效的keys及时失效
// - CHECK_INTERVAL = 300 扫描缓存的间隔

@Scheduled(fixedRate = CHECK_INTERVAL * 1000)
public void cleanExpiredCache(){
Set keys = redisTemplate.keys("*");
while (true) {
String[] keyArr = keys.toArray(new String[MAX_KEYS_NUM]);
keys = keys.size() > MAX_KEYS_NUM ?
new HashSet(keys.subList(MAX_KEYS_NUM, keys.size())) :
new HashSet();
List expiredKeys = new ArrayList();
for (String key : keyArr) {
if (redisTemplate.getExpire(key)
expiredKeys.add(key);
}
}

if (expiredKeys.size() > 0) {
redisTemplate.delete(expiredKeys);
}

if (keys.size() == 0) {
break;
}
}
}

2. 通过命令进行清理,如 INFO 命令,查看过期key的总数,以及对过期key进行清理的命令:

// 查看过期key的总数
info memory | grep expired

// 对过期key进行清理
redis-cli --scan --pattern '*' | xargs redis-cli unlink

3. 此外,也可以使用redis提供的脚本功能,每当新增/更新缓存时,就把该key的时间封装入Set集合,然后每隔一段时间把集合里面所有超时key清理掉:

// 缓存设置时,把key设置进SET集合
public void setKey(String key,Object value){
// set缓存
redisTemplate.opsForValue().set(key,value);
// 把key插入到SET
redisTemplate.opsForSet().add("expiredKeySet",key);
}
// 防止大量的key操作,把过期的key放在一个SET中,每隔一段时间清理它:
@Scheduled(fixedRate = CHECK_INTERVAL * 1000)
public void cleanExpiredCache(){
// 向SET中添加keys
Set keys = redisTemplate.opsForSet().members("expiredKeySet");
for(String key:keys){
if (redisTemplate.getExpire(key)
// 移除key
redisTemplate.delete(key);
// SET中移除
redisTemplate.opsForSet().remove("expiredKeySet", key);
}
}
}

上面是几种处理方案,当然也可以结合以上、自定义更好的定时清理机制,确保Redis的缓存可以随着时间轮番更新,以及保证Redis的使用效率。


数据运维技术 » 定时清理Redis妙招不断(怎么定时清理redis)