mirror of https://github.com/dunwu/db-tutorial.git
53 lines
3.5 KiB
Markdown
53 lines
3.5 KiB
Markdown
|
# 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 这个字典表中。
|