定期删除
在上文中我们提及了俩种删除方式,一种是定时删除,一种是惰性删除。一个是用空间换时间。一个是用时间换空间。俩种方案都是比较极端的方式。那么接下来我们在来看看定期删除的实现方案。
先来看一下redis的存储空间,一共有默认为16个,在redis.conf里边有一个配置参数database这个参数控制的。每个数据库都有自己的过期分区,里边存储就是数据地址 和 数据过期时间。
实现方式
redis在启动时,会取读取server下的hz的值,默认为10。这个值直接在终端使用info server就可以查看的到
然后会每秒钟执行server下hz次 进行serverCron()轮询
继续使用databasesCron对redis的16个库进行挨个访问信息
访问时候会再执行activeExpireCycel对每个expires[*]逐一进行检测,每个执行的时间为250ms / server hz这个参数
在对每个expirs[*]逐一检测时,会随机拿出ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC个可以进行检测
- 如果key超时,直接删除key
- 一轮中删除的key数量>ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC*25%继续循环该过程
- 如果一轮中删除的key数量<=ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC25% ,检查下一个expires[]
那么现在问题来了,我们的250ms / hz这个时间执行完了,但是把expires的16个数据库没有循环完怎么办呢! 下次来在循环那个库呢! 其实这个值是有存的,就是current_db这个值。这个值会记录activeExpireCycel 下次进入那个expires[*]执行
特点1:CPU使用没有高峰值,检测频率自定义设置
特点2:内存压力不会很大, 长时间占用的内存会被持续的清理
逐出算法
在上文中我们说了三种删除策略,但是这三种策略都是相对于设置了有效期的key才会有效。
那现在我们的redis使用的内存不足了,就会使用逐出策略来保证redis的正常使用。
redis在每次执行命令前会调用freeMemorylfNeeded()检测内存是否充足,当不充足时就会清理一些key,这种清除数据的策略称为逐出策略。
redis最大可使用内存的参数为:maxmemory 默认为0 指的是占用物理内存的比例 一般设置50%就可以了
每次选取待删除key的个数:maxmemory-samples
删除策略:maxmemory-policy
下面我们来着重说明删除策略
检测易失数据(也就是我们设置了有效期,但是还没有到期的数据,就是上文expires[*])
- volatile-lru:挑选最近少使用的数据
- volatile-lfu:挑选最近使用次数最少的数据
- volatile-ttl:挑选将要淘汰的数据
- volatile-random:随机选择
接下来看一幅图
- 9s就是现在的时间
- 距离9s最长的一个key就是age
- 使用次数最少的就是gender这个key
- 如果按照volatile-lru就会把age删除掉
- 如果按照volatile-lfu就会把gender删除掉
检测全部数据
allkeys-lru:挑选最近少使用的数据
allkeys-lfu:挑选最近使用次数最少的数据
allkeys-random:全库随机删除
放弃数据驱逐
no-enviction : 数据不会进行任何的删除,直到内存用完,引发oom错误。
总结
以上就是redis对数据的删除策略和逐出策略。
这里就一个注意点就是在逐出策略中,易失数据指的是设置了过期时间的key,并非永久性的值。
全库是指的全部的值,设置了过期时间和永久数据。