为什么要删除数据
随着服务器的运行,Redis 中的数据量会越来越大,但并非每一条数据都是必须的,为了降低不必要的内存消耗,需要对 Redis 中的数据进行删除
Redis 的三种删除策略
定时删除
基本思想
当 key 设置有过期时间的时候,创建一个定时器,过期时间到达时,由定时器立即执行对 key 的删除
优点
缺点
- 无论当前 CPU 压力是否过大,都会立即占用 CPU 执行删除任务,影响 Redis 服务器响应时间和吞吐量
总结
定时删除是一种用 CPU 性能换取内存空间的删除策略
惰性删除
基本思想
数据到达过期时间后,不做处理,下次访问该数据时,删除该数据并返回不存在
本质上是在读写该数据前调用 expireIfNeeded() 方法
- 如果数据已经过期,那么 expireIfNeeded() 将该数据从数据库中删除
- 如果数据未过期,那么 expireIfNeeded() 不做处理
优点
- 节约 CPU 性能,只有当必须要删除时才执行删除任务
缺点
- 当长时间未获取某些过期数据后,会使得大量数据长期占用内存,造成内存压力过大
总结
惰性删除是一种用内存空间换取 CPU 性能的删除策略
定期删除
实现流程
- Redis 服务器初始化时,读取配置中 server.hz 的值,默认是 10
- 对服务器进行定时轮询,每秒执行 server.hz 次 serverCron() 函数
- serverCron() 函数中,通过 databasesCron() 函数对每个数据库进行轮询
- 通过?activeExpireCycle() 函数对每个数据库的 expires?空间进行检测,每次执行 250ms/server.hz
- 对该 expires 空间随机挑选 W 个 key 进行检测
- 如果 key 过期,则删除
- 如果一轮中删除的 key 数量>0.25W ,再循环一轮(在剩下的 key 中重新随机挑选 W 个进行检测)
- 如果一轮中删除的 key 数量 ≤ 0.25W ,进行下一个数据库的 expires?空间的检测
在?redis.windows.conf(Linux 下为 redis.conf)中配置 hz 的值,用 info server 指令查看
总结
- 可以灵活的自定义检测频率,利用过期数据占比情况控制删除频率,保证了 CPU 占用不会过高
- 内存定期随机清理,一定程度上降低了内存压力
逐出(淘汰)策略
Redis 在执行指令前,会调用freeMemoryIfNeeded() 函数检测内存空间是否足够,若不足则会临时删除一些数据来为当前指令提供足够的内存空间,此时的删除策略称为逐出(淘汰)策略
相关配置
参数名 | 默认值 | 说明 |
---|
maxmemory | 0(表示不限制) | 最大可使用内存 | maxmemory-samples | 5 | 每次随机选取待删除数据的个数 | maxmemory-policy | volatile-lru(Redis4.0前) no-enviction(Redis4.0后) | 对挑选出来的数据进行删除的策略 |
检测易失数据
- volatile-lru(Least Recently Used):最近最少使用算法,从设置了过期时间的 key 中选择最长时间没有使用的?key 删除
- volatile-lfu(Least Frequently Used):最近最不经常使用算法,从设置了过期时间的 key 中选择某段时间内使用次数最少的 key 删除
- volatile-ttl(Time To Live):从设置了过期时间的 key 中选择过期时间最早的 key 删除
- volatile-random:从设置了过期时间的 key 中,随机选择 key 删除
检测全库数据
-
allkeys-lru(Least Recently Used):最近最少使用算法,从所有的 key 中选择最长时间没有使用的?key 删除 -
allkeys-lfu(Least Frequently Used):最近最不经常使用算法,从所有的 key 中选择某段时间内使用次数最少的 key 删除 -
allkeys-random:从所有的 key 中,随机选择 key 删除
放弃逐出
- no-enviction:禁止逐出数据,当内存不足以容纳新数据时,写入操作就会报错,采用该策略可以保证数据不被丢失
|