redis-11 redis清除过期 key 详解

始因

  有时候线上可能会遇到这样的问题:

  明明我设置了对应的 key 以及超时时间,但是在使用的过程当中发现对应的 key 丢失了,尤其是在用户账号登录状态保持有效期的场景下,会越发的明显。即:一个用户正常登录会产生一个有效期为一天的 token,这样用户再次进入网站是不需要登录的。但是发生 key 丢失问题就会导致用户需要频繁的重新登录,用户体验相当不好。导致这种问题的原因一般有以下两种情况:

  1. token 生成时出现逻辑问题

  2. 验证 token 时出问题了

  对于上线稳定的项目来说,发生 1 的概率基本为 0。那么会立马定位到 2 的情况。这种情况就会引发我们今天讨论的问题:

  redis 如何自动清理过期 key,以及对应 key 没有过期但是也会被清理掉呢?

近似 LRU

  在解释近似LRU之前,先来简单了解一下LRU。

  当Redis的内存占用超过我们设置的 maxmemory 时,会把长时间没有使用的key清理掉。按照 LRU算法,我们需要对所有key(也可以设置成只淘汰有过期时间的key)按照空闲时间进行排序,然后淘汰掉空闲时间最大的那部分数据,使得Redis的内存占用降到一个合理的值。

  LRU算法的缺点:

    1. 我们需要维护一个全部(或只有过期时间)key的列表,还要按照最近使用时间排序。这会消耗大量内存

    2. 每次操作 key 时更新对应维护列表的排序也会占用额外的CPU资源。

  对于Redis这样对性能要求很高的系统来说是不被允许的。

  因此,Redis采用了一种 近似LRU 的算法。当Redis接收到新的写入命令,而内存又不够时,就会触发 近似LRU 算法来强制清理一些key。

  具体清理的步骤是:

    1. Redis会对 key 进行采样,通常是取5个,然后会把过期的key放到我们上面说的“过期池”中

    2. 过期池中的 key 是按照空闲时间来排序的,Redis 会优先清理掉空闲时间最长的 key,直到内存小于 maxmemory。

  其中 Redis首先是采样了一部分key,这里采样数量 maxmemory_samples 通常是5,我们也可以自己设置,采样数量越大,结果就越接近LRU算法的结果,带来的影响是:性能随之变差。

清理策略

  最后我们来看一下Redis支持的几种清理策略

    1. noeviction:不会继续处理写请求(DEL可以继续处理)。

    2. allkeys-lru:对所有key的近似LRU

    3. volatile-lru:使用近似LRU算法淘汰设置了过期时间的key

    4. allkeys-random:从所有key中随机淘汰一些key

    5. volatile-random:对所有设置了过期时间的key随机淘汰

    6. volatile-ttl:淘汰有效期最短的一部分key

  Redis4.0 开始支持了 LFU 策略,和 LRU 类似,它分为两种:

    7. volatile-lfu:使用LFU算法淘汰设置了过期时间的key

    8. allkeys-lfu:从全部key中进行淘汰,使用LFU

最后

  针对文章开始提到的问题,最好的解决办法是将使用内存量较大的业务 和 用户账号服务 使用的 redis 隔离开,这样就单个用户账号正常情况下是不会发生以上类似的问题了。


  

猜你喜欢

转载自www.cnblogs.com/liang1101/p/12932400.html