mirror of https://github.com/dunwu/db-tutorial.git
3.5 KiB
3.5 KiB
Redis 缓存淘汰策略
概述
- 最大缓存
Redis 允许通过 maxmemory 参数来设置内存最大值。
- 主键失效
作为一种定期清理无效数据的重要机制,在 Redis 提供的诸多命令中,EXPIRE、EXPIREAT、PEXPIRE、PEXPIREAT 以及 SETEX 和 PSETEX 均可以用来设置一条 Key-Value 对的失效时间,而一条 Key-Value 对一旦被关联了失效时间就会在到期后自动删除(或者说变得无法访问更为准确)。
- 淘汰机制
随着不断的向 redis 中保存数据,当内存剩余空间无法满足添加的数据时,redis 内就会施行数据淘汰策略,清除一部分内容然后保证新的数据可以保存到内存中。
内存淘汰机制是为了更好的使用内存,用一定得 miss 来换取内存的利用率,保证 redis 缓存中保存的都是热点数据。
- 非精准的 LRU
实际上 Redis 实现的 LRU 并不是可靠的 LRU,也就是名义上我们使用 LRU 算法淘汰键,但是实际上被淘汰的键并不一定是真正的最久没用的。
淘汰策略
内存淘汰只是 Redis 提供的一个功能,为了更好地实现这个功能,必须为不同的应用场景提供不同的策略,内存淘汰策略讲的是为实现内存淘汰我们具体怎么做,要解决的问题包括淘汰键空间如何选择?在键空间中淘汰键如何选择?
Redis 提供了下面几种淘汰策略供用户选择,其中默认的策略为 noeviction 策略:
- noeviction - 当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
- allkeys-lru - 在主键空间中,优先移除最近未使用的 key。
- allkeys-random - 在主键空间中,随机移除某个 key。
- volatile-lru - 在设置了过期时间的键空间中,优先移除最近未使用的 key。
- volatile-random - 在设置了过期时间的键空间中,随机移除某个 key。
- volatile-ttl - 在设置了过期时间的键空间中,具有更早过期时间的 key 优先移除。
这里补充一下主键空间和设置了过期时间的键空间,举个例子,假设我们有一批键存储在 Redis 中,则有那么一个哈希表用于存储这批键及其值,如果这批键中有一部分设置了过期时间,那么这批键还会被存储到另外一个哈希表中,这个哈希表中的值对应的是键被设置的过期时间。设置了过期时间的键空间为主键空间的子集。
如何选择淘汰策略
- 如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用 allkeys-lru。
- 如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用 allkeys-random。
- volatile-lru 策略和 volatile-random 策略适合我们将一个 Redis 实例既应用于缓存和又应用于持久化存储的时候,然而我们也可以通过使用两个 Redis 实例来达到相同的效果。
- 将 key 设置过期时间实际上会消耗更多的内存,因此我们建议使用 allkeys-lru 策略从而更有效率的使用内存。
内部实现
Redis 删除失效主键的方法主要有两种:
- 消极方法(passive way),在主键被访问时如果发现它已经失效,那么就删除它。
- 主动方法(active way),周期性地从设置了失效时间的主键中选择一部分失效的主键删除。
- 主动删除:当前已用内存超过 maxmemory 限定时,触发主动清理策略,该策略由启动参数的配置决定主键具体的失效时间全部都维护在 expires 这个字典表中。