Redis 超时失效 Key 监听不及时原因分析及解决方案

Redis 共有 3 种过期策略: 定时删除、惰性删除、定期删除
三者对比如下:

说明 优点 缺点
定时删除 在设置 Key 过期时间的同时创建定时器,让定时器在 Key 过期时执行删除操作 保证过期数据能被及时删除 耗 CPU,尤其当存在大量非永久 Key 时,对 CPU 影响更严重
惰性删除 Key 过期时不主动删除,获取数据时判断该 Key 是否过期,如果过期直接删除 对 CPU 消耗小 耗内存,如果数据过期但又没有任何操作来获取该数据,哪怕数据已经过期了,但该数据任会一直存在
定期删除 每隔一段时间执行一次删除操作 不如定时删除那么消耗 CPU,也不如惰性删除那么占内存 比定时删除更消耗内存,必惰性删除更消耗 CPU

原因
默认情况下,Redis 使用的是 惰性删除 + 定期删除 的策略,过程如下:

  1. 每隔一段时间,Redis 会分别去各个库随机拿 20 个非永久 Key,判断它们是否过期,过期则删除,如果这一次拿的 key 中有超过 1/4 的数据过期,则再执行一遍过程 1,直到过期数据不超过当次拿出来的 20 条记录的 1/4(可以通过配置 redis.conf 中的 hz 修改 Redis 执行定期删除的频率,默认 hz=10 ,即每 100ms 执行一次, 1/4 与每次拿的数量 20 暂时未找到配置项);
  2. 如果当前数据库没有非永久 key,则跳过当前数据库;
  3. 如果 key 已过期,但没有在步骤 1 中被定期删除,由于惰性删除策略,在下次请求获取该数据时会将该数据删除;

通过对 Redis 删除策略的解读,可以得出如下结论:

如果每次从 Redis 数据库中拿的 20 条记录中,过期的不足 1/4,则本次定期删除流程结束 ==>> 如果同一 Redis 数据库中同时存在缓存数据及要做超时监听的 key,并且缓存数据远大于超时监听 key 数,那么在定期删除时监听的 key 被拿出来的概率便会很小,由此导致 Key 过期监听不及时

解决方案

  1. 将缓存数据与监听数据分离,即把不同功能类型的数据分库存放(Redis 默认有 16 个库,库的数量可在 redis.conf 配置修改),例如把缓存数据存在 database0,把监听数据存在 database1;
  2. 让进行监听的库中 key 尽量少,如果不同业务的监听超时时间差异较大,则考虑将不同业务的超时监听数据存放到不同的数据库;

原文:https://blog.csdn.net/shawearn1027/article/details/103427358
作者: 青年老魏