背景
Redis 之所以有淘汰策略,是因为 Redis 是基于内存的高性能键值存储系统,它将数据全部加载到内存中进行读写操作。但是,内存资源是有限的,当 Redis 使用的内存接近或超过系统可用内存时,就需要通过一些策略来释放内存空间。
1)键过期:通过expire / pexpire 设置key的生存时间。当key的生存周期达到时,将对应的key-value删除。
# 设置 key 的过期时间 expire key seconds pexpire key milliseconds # 查看 key 的过期时间 ttl key pttl key
2)键的空闲时间(空转时长):redis每次操作value时,会记录操作的时间戳和统计对key-value的操作次数。value 的类型有多种,底层由 redisObject 实现,这种通用的数据结构可以存储不同类型的 value。
typedef struct redisObject { unsigned type:4; // 对象类型:string, hash, list, set unsigned encoding:4; // 编码方式 unsigned lru:LRU_BITS; // lru:24位,最近一次访问时间,单位秒, // lfu: 高16位,最近一次访问时间;低8位,逻辑访问次数 int refcount; // 引用计数,计数为 0,对象无人引用,可以回收 void *ptr; // 数据指针,指向对象内容 } robj;
lru字段用于记录操作value的时间,也会统计对key-value操作了多少次。可以使用object idletime key
获取指定键的空闲时间。空闲时间指的是自上次对该键进行读取或写入操作以来所经过的时间。
# 对象空转时长 object idletime key
3)配置 redis.conf有两个参数配置淘汰策略,maxmemory和maxmemory-policy。 maxmemory限定redis可以使用的最大内存(单位是字节 ),一般设置为当前系统可用内存的一半; maxmemory-policy用于制定淘汰策略。
# redis.conf maxmemory <bytes> maxmemory-policy noeviction
淘汰策略
针对过期key
- volatile-lru:从设置了过期时间的键中,选择最近最少使用(Least Recently Used)(最长时间没有使用)的键进行删除。这种模式下, lru整个字段都用于记录时间。
- volatile-lfu:从设置了过期时间的键中,选择最少使用次数的键进行删除。这种模式下 记录操作的时间和统计对key-value操作次数(8位统计次数,16位记录时间)。
- volatile-ttl:从设置了过期时间的键中,选择剩余时间最短(最近就要过期)的键进行删除。这种模式下,记录操作的时间和统计对key-value操作次数(8位统计次数,16位记录时间)。
- volatile-random:从设置了过期时间的键中,随机选择一个进行删除。ttl/pttl指令可以查询key还有多长时间到期。
针对所有key
- allkeys-lru:从所有的键中,选择最近最少使用的键进行删除。无论键是否设置了过期时间。
- allkeys-lfu,从所有的键中,选择最少使用次数的键进行删除。无论键是否设置了过期时间。
- allkeys-random:从所有的键中,随机选择一个进行删除。无论键是否设置了过期时间。
禁止淘汰
noeviction:默认是禁止淘汰,如果数据达到了最大内存限制,在向redis中写入数据时会报错。