Redis 存储机制及淘汰策略
RDB(快照)
RDB 持久化方式会在一个特定的间隔保存那个时间点的一个数据快照
AOF(记录所有更新操作)
AOF 持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟 Redis 协议一致,以追加的方式进行保存。
Redis 的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。两种方式的持久化是可以同时存在的,但是当 Redis 重启时,AOF 文件会被优先用于重建数据。
使用 AOF
开启:修改 redis.conf 文件 appendonly yes
重启 Redis 即创建文件 appendonly.aof
✘ seth@mac /usr/local/var/db/redis tree -L 2
.
├── appendonly.aof
└── dump.rdb
cat appendonly.aof
*2
$6
SELECT -> select
$1
0 -> db0
*3
$3
set -> operation
$5
hello -> key
$1
2 -> value
淘汰策略
Redis 提供了下面几种淘汰策略供用户选择,其中默认的策略为 noeviction
策略:
- noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错
- allkeys-lru:在主键空间中,优先移除最近未使用的key
- volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的 key
- allkeys-random:在主键空间中,随机移除某个 key
- volatile-random:在设置了过期时间的键空间中,随机移除某个 key
- volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的 key 优先移除
这里补充一下主键空间和设置了过期时间的键空间,举个例子,假设我们有一批键存储在Redis中,则有那么一个哈希表用于存储这批键及其值,如果这批键中有一部分设置了过期时间,那么这批键还会被存储到另外一个哈希表中,这个哈希表中的值对应的是键被设置的过期时间。设置了过期时间的键空间为主键空间的子集。
常用 LRU(Least Recently Used)
- 设置缓存大小
maxmemory <bytes>
- 设置淘汰策略
maxmemory-policy allkeys-lru
但是这个值填什么呢?为解决这个问题,我们需要了解我们的应用请求对于 Redis 中存储的数据集的访问方式以及我们的诉求是什么。同时 Redis 也支持 Runtime 修改淘汰策略,这使得我们不需要重启 Redis 实例而实时的调整内存淘汰策略。
非精准的 LRU
上面提到的 LRU(Least Recently Used)策略,实际上 Redis 实现的 LRU 并不是可靠的 LRU,也就是名义上我们使用 LRU 算法淘汰键,但是实际上被淘汰的键并不一定是真正的最久没用的,这里涉及到一个权衡的问题,如果需要在全部键空间内搜索最优解,则必然会增加系统的开销,Redis 是单线程的,也就是同一个实例在每一个时刻只能服务于一个客户端,所以耗时的操作一定要谨慎。为了在一定成本内实现相对的 LRU,早期的 Redis 版本是基于采样的 LRU,也就是放弃全部键空间内搜索解改为采样空间搜索最优解。自从 Redis3.0 版本之后,Redis 作者对于基于采样的 LRU 进行了一些优化,目的是在一定的成本内让结果更靠近真实的 LRU。