Redis高级特性----删除策略 (个人学习笔记)
过期数据
首先我们来看Redis的数据特征,Redis是一种内存级的数据库,所有的数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态
操作命令:
ttl key
以及
pttl key
获取得到得状态及其解释如下
-
XX : 具用时效性得数据
-
-1 : 永久有效得数据
-
-2 : 已经过期 或 被删除以及未定义得数据
根据以上的状态,那么现在我们来思考一个问题,在redis中过期的数据也就是上述状态为-2的数据会立即被删除吗?
答案是否定的
我们的Redis的数据是存储在内存中的,而添加删除等指令是由CPU操作,为了保障在CPU高负载的情况下,业务的正常处理,删除并不会立马执行
还要明白的一个概念是时效性数据的存储结构
我们都知道,设置一个key的value时,在value内还会存储该值的内存地址,而过期数据是一块独立的存储空间,Hash结构,field是内存地址,value是过期时间,保存了所有key的过期描述,在最终进行过期处理的时候,对该空间的数据进行检测, 当时间到期之后通过field找到内存该地址处的数据,然后进行相关操作
所以操作过期数据结构的策略便就是数据删除策略,有如下三种策略
- 定时删除
- 惰性删除
- 定期删除
值得注意的是,使用数据删除策略并不是简简单单的删除数据,而是在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能的下降,甚至引发服务器宕机或者内存泄漏
定时删除
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
- 优点:节约内存,到时就删除,快速释放掉不必要的内存占用
- 缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
- 总结:用处理器性能换取存储空间(拿时间换空间)
惰性删除
数据到达过期时间,不做处理。等下次访问该数据时,我们需要判断
- 如果未过期,返回数据
- 发现已过期,删除,返回不存在
值得注意的,我们在使用数据时是如何发现数据过期的,其实在我们执行指令前系统都会默认执行一个EXPIREIFNEEDED函数,也可以说这个函数和get之类的指令是绑定在一起的,这个函数就是用来查询数据是否过期的函数
- 优点:节约CPU性能,发现必须删除的时候才删除
- 缺点:内存压力很大,出现长期占用内存的数据
- 总结:用存储空间换取处理器性能(拿时间换空间)
定期删除
定时删除和惰性删除这两种方案都是走的极端,那有没有折中方案?
我们来讲redis的定期删除方案:
-
Redis启动服务器初始化时,读取配置server.hz的值,默认为10
-
每秒钟执行server.hz次serverCron()-------->databasesCron()--------->activeExpireCycle()
-
activeExpireCycle()对每个expires[*]逐一进行检测,每次执行耗时:250ms/server.hz
-
对某个expires[*]检测时,随机挑选W个key检测
如果key超时,删除key 如果一轮中删除的key的数量>W*25%,循环该过程 如果一轮中删除的key的数量≤W*25%,检查下一个expires[*],0-15循环 W取值=ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP属性值
-
参数current_db用于记录activeExpireCycle() 进入哪个expires[*] 执行
-
如果activeExpireCycle()执行时间到期,下次从current_db继续向下执行
总的来说:定期删除就是周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度 -
特点1:CPU性能占用设置有峰值,检测频度可自定义设置
-
特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理
-
总结:周期性抽查存储空间(随机抽查,重点抽查)