一.由来
因为现在Redis的使用是非常普遍的,Redis是基于内存的数据存储系统,而内存相比于早些年而言,还是便宜了很多,但是相比硬盘而言还是最很多,因此提高Redis里面的内存利用率是非常重要,而Redis的过期策略就是提升内存空间利用率的一把利刃,同时还存在另一个利刃就是内存淘汰策略。
二.过期策略
两种策略:
1.定期删除:定时定期的删除某些数据;
默认会隔一段时间来Redis中随机抽取一些我们设定了过期时间的Key出来,然后来足个分析这些Key是否已经过期,那么说如果这些Key已经过期了(TTL=0),那么就就会将这些数据进行删除,不会将这个数据直接返回给用户,如果说我们抽取出来的Key中已经过期的Key的占比大于抽取出来的数据的25%,那么代表需要删除的有很多,此时会立刻进入下一轮的随机抽取,直到有一次这个占比小于25%,这个时候才会结束这个随机抽取动作,然后根据设置的间隔时间,才会进入下一轮。
Redis默认是每个100ms就随机抽取一些设置了过期时间的Key,检查是否过期,过期就删除。
但是这种会出现两个问题:
(1)随机抽取出来的这个Key很多的话,就需要足个比对,这个时候就会占用大量的CPU资源,从而会影响到Redis的性能;
(2)随机抽取数据,也就意味着在Redis里面肯定会存在一些漏网之鱼,比如上面的K1值,每次抽取都没有抽到它,但是它已经过去,也就代表这个Key不会被删除掉,它就会继续浪费Redis里面的内存空间。
2.惰性删除:存在一种懒加载的思想在里面,需要触发某个常见才能删除某些数据。
只有当用户访问到某一个Key的时候,才会进行检查Key是否过期,过期就删除,不返回任何东西,没有访问到的Key就会一直存在Redis中,这也没能解决到定期删除的漏网之鱼问题,也就是这个Key既没有被访问到,也没有被随机抽选到,这个Key还是会继续遗忘在Redis里面,浪费内存空间。
为了解决这个问题,就需要使用到内存淘汰机制,
三.内存淘汰策略
常见八种策略:
它主要涉及到Lru的算法(根据使用时间)和Lfu的算法(根据使用频率)。
1.noevication(3.0版本后的默认策略):当内存使用超过配置的大小时,直接报错;
2.allkeys-lru:在所有Key里面来实行lru算法,根据算法来删除最久没有使用的键;
3.volatile-lru:在设置了过期时间的Key里面来实行lru算法,根据算法来删除最久没有使用的键;
4.allkeys-random:在所有Key里面,随机挑去一部分Key进行删除;
5.volatile-random:在设置了过期时间的Key里面,随机挑去一部分Key进行删除;
6.volatile-ttl:在设置了过期时间的Key里面根据TTL时间进行筛选数据,其实就是选择剩余时间最短的Key进行删除,比如现在有两个Key,一个Key还有10s过期,一个Key还有20s过期,它会有限删除10s的Key;
7.volatile-lfu:在设置了过期时间的Key里面来实行lru算法,根据算法来删除使用频率最少的键;
8.allkys-lfu:在所有Key里面来实行lfu算法,根据算法来删除使用频率最少的键;
四.问题
1.如果数据库有1000万条数据,而Redis只能缓存20万条数据,如何保证Redis中都是热点数据?
答:可以使用allkeys-lru(
挑选最近最少使用的数据淘汰)淘汰策略,这样留下来的都是经常访问的热点数据。
2.当Redis的内存用完了会发生什么?
答:主要取决于数据淘汰策略。如果是默认的配置(noeviction)
,Redis会直接报错,因为无法删除任何数据以腾出内存空间。