过期数据
Redis的所有数据都存放在内存中的,并且有TTL值,TTL和网络不同,其数值
- 为XX时,表示具有时效性的数据
- 为-1时,表示永久有效
- 为-2时,表示已经过期的或者已经被删除的或者未定义的
当数据到达有效期之后,就会被定义为过期数据
Redis对于过期数据有三种删除策略,分别为
- 定时删除
- 惰性删除
- 定期删除
其中关于数据的过期时间值是有一块专门的地方以键值对方式存下来的
数据删除策略的目标:在内存占用与CPU占用之间寻找一个平衡
删除策略
定时删除
创建一个定时器,当key设置的定期时间到达时,由定时器任务立即执行对key的删除操作
- 优点:节约内存
- 缺点:CPU压力大
- 总结:以时间换空间
惰性删除
数据到达过期时间,不立即删除,等下次访问数据时再删除
原理:所有的get操作都会包含对于expirelfNeeded()
方法的执行,这个方法的作用就是判断key是否过期
- 优点:节约CPU性能
- 确定:内存占用大
- 总结:以空间换时间
定期删除
当Redis启动时,读取server.hz
的值,默认为10,之后每秒钟都会执行server.hz
次serverCron()
方法
每一次serverCron()
方法都会执行databasesCron()
方法
每一次databasesCron()
方法都会去轮询服务器中的Redis数据库,并且执行activeExpireCycle()
方法
每一次activeExpireCycle()
方法都会对每个expires[*]进行检测,每次执行250ms/server.hz(最多占用1/4个CPU)
对某个expires[*]检测时,随机挑选W个key检测:
- 如果key超时,删除key
- 如果第一轮中删除的key数量大于0.25*W,继续循环
- 如果第一个中删除的key数量小于0.25*W,检查下一个expires[*]
W的取值为ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
属性值
参数current_db
会记录activeExpireCycle()
进入的expire索引,如果activeExpireCycle
方法执行到期,下次会从current_db
继续向下执行
特点:
- 轮询、随机抽取、控制占比
- CPU占用可控
- 内存压力不大
- 周期性的抽查
逐出策略
Redis执行每一个存储命令前都会调用freeMemoryIfNedded()
方法检测内存是否充足,如果不足的话就会临时清一点空间出来,这种清理的策略叫做逐出算法
当然逐出算法不一定能成功的,如果失败的话会返回错误信息(OOM)
影响逐出的相关配置
maxmemory # 最大可用内存(占用物理内存的比例,默认为0代表不限制,通常限制50%以上)
maxmemory-samples # 每次选取待删除的数据个数(选取是随机选取作为逐出候选目标的)
maxmemory-policy # 到达最大内存后,逐出的策略
关于策略:
检测易失数据
volatile-lru
:LRU策略volatile-lfu
:LFU策略volatile-ttl
:挑选最马上要过期的淘汰volatile-random
:随机抽取幸运儿淘汰
检测全库数据
allkeys-lru
:LRUallkeys-lfu
:LFUallkeys-random
:random
放弃数据驱逐
no-enviction
:Redis4.0默认策略,会引发OOM