Redis-内存淘汰和过期key删除

Reid 缓存的空间容量必然要小于后端数据库的数据总量。不过,内存大小毕竟有限,随着要缓存的数据量越来越大,有限的缓存空间不可避免地会被写满。此时,该怎么办呢?解决这个问题就涉及到缓存系统的一个重要机制,即缓存数据的淘汰机制。简单来说,数据淘汰机制包括两步:第一,根据一定的策略,筛选出对应用访问来说“不重要”的数据;第二,将这些数据从缓存中删除,为新来的数据腾出空间。
为了避免频繁的数据淘汰,一般建议将内存容量调整为合适大小,通常遵循二八定律,占后端数据库的二成,当然也要实际情况为准。
另外 redis 占用的内存大小一定大于实际的数据大小,因为有数据碎片和其他结构占用的内存。
可以使用下面这个命令来设定缓存的大小了:CONFIG SET maxmemory 4gb
内存淘汰策略
在内存不够用的时候会触发内存淘汰,避免内存不够而崩溃,那怎么淘汰呢?
-
volatile-ttl 在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。
-
random 就像它的名称一样,进行随机删除。
-
lru 会使用 LRU 算法筛选键值对,一直没被使用的元素被淘汰。
普通的 lru 算法是通过队列来实现的,最近被访问的数据移动到队头,队尾就是最近最少被访问的数据,会被删除。
redis 中的 lru 算法不同于普通的 lru 算法,他不采用队列来实现,是因为维护队列需要额外的内存空间。他的实现方式是,为每个数据记录了最新以此被访问的时间戳,在触发淘汰时,随机选择N个数据, 把时间戳最小的淘汰。再次出发时,再从外面找一个比 N-1 个数据时间戳更小的数据进来,再淘汰。
-
lfu 会使用 LFU 算法淘汰键值对,最近最少被使用的元素淘汰。
和 lru 算法类似,是对其的增强。实现方式是,为每个元素记录时间戳和访问次数,先比较访问次数,最少的被淘汰,一样的话就比较访问时间,时间戳最小的被淘汰。并且访问次数会随着时间而递减,这样可以淘汰掉那些短时间被大量访问后就不再访问的数据。
优先选择 lfu 策略,如果业务上没有明显的冷热数据区分,就选择 allkeys-random 的策略。如果业务上有置顶需求,或者一些一定不能被删除的数据,那么就选择 volatile-lru。
过期Key删除策略
惰性删除
惰性删除是指过期 key 的删除策略,设置了过期时间的 key ,在到达了过期时间时,redis 并不会删除他,而是在该数据被访问时删除。
定期删除
redis开启一个后台线程,每隔一段时间执行以此,随机选择若干个数据,如果其中已经过期的数据占比超过 25% ,就删除他们,循环此操作,直到比例低于 25% 。
-
过期 key 在 RDB 时是怎么处理的?
在备份过程中 ,已经过期的数据不会被持久化到 RDB 文件中。
在恢复过程中,已经过期的数据不会被恢复到内存中。
-
过期 key 在 AOF 时是怎么处理的?
已过期但是没被删除的 key ,不会触发 AOF 。
已过期被删除的 key , 会写一条 del 命令到 AOF 中。这样数据恢复时就能正常了。
AOF 重写过程中会对于过期的 Key ,是不会被写入到新的 AOF 文件中的。
过期 key 的删除和内存淘汰是两个概念,没关系。内存淘汰发生在内存不够时,过期 key 的删除发生在任何时候。不要把两者混为一谈,虽然实际上他们都是 redis 内存管理的方案。