删除策略
过期数据
Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态:
- XX:具有时效性的数据
- -1:永久有效的数据
- -2:已经过期的数据或被删除的数据或未定义的数据
时效性数据的存储结构
删除策略是对expires的维护。
删除数据的策略
定时删除
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作。
当前时间和expires中对过期时间一致时,定时器触发删除。
优点:节省内存,到时间就删除,快速释放不必要的内存占用。
缺点:CPU压力较大,无论CPU此时负载情况如何,均占用CPU来执行删除,会影响Redis服务器的响应时间和指令吞吐量。
时间换空间
惰性删除
数据到达过期时间,不做处理,等下次访问该数据等时候执行删除。
在获取数据时,内部会调用expirelfNeeded()方法,来确定数据是否到期。
- 未到期,返回数据。
- 到期,删除,返回不存在。
优点:节约cpu性能,到了必须删除的时候才执行删除。
缺点:内存压力较大,会出现长期占用内存的数据。
空间换时间
定期删除
Redis的存储空间中,每个db都有一个expires。整体的结构如下:
- Redis服务器启动初始化的时候,读区配置中的server.hz,默认为10。代表每秒执行10次serverCron()操作。
- 在serverCron()中会调用databasesCron()来轮询每一个db(即循环expire[*])。
- 在databasesCron()中会调用activeExpireCycle()方法,对每一个expire[*]进行检测,每次执行的时长伟250ms/server.hz。
- 对某个expire[*]检测时,随机挑选W个key进行检测。如果key超时,即删除。
- 如果第四步中,删除的key的数量大于W*25%,则继续在此expire[*]上检测执行。
- 如果第四步中删除的key的数量小于等于W*25%,则检测下一个expire[*]。(从0-15循环,Redis默认为16个DB)
其中W值,可以在配置文件中配置,对应的属性为ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;
在第四步中的activeExpireCycle()方法执行检测的时候,因为时间长度时固定的,下一次activeExpireCycle()方法执行为了接着上一次中断的位置执行,用参数current_db来记录当前检测的expire。
特点:对cpu的使用有峰值,也有一定的自定义空间。删除过程中,内存的压力也不是很大。
Redis采用的策略:惰性删除+定期删除。
逐出策略
Redis使用内存存储数据,在执行每一天命令前,都会调用freeMemorylfNeeded()检测内存释放充足,如果内存不满足要加入数据的最低要求,redis会临时删除一些数据为当前指令清理存储空间。清理数据的策略称为逐出算法。
逐出策略并不保证100%能清理出可使用的内存空间,如果不成功就反复执行。当对所有数据尝试完成后,如果不能达到内存清理的要求,将出现错误信息(OOM)。
相关配置
maxmemory:最大可使用内存。占用物理内存的比例,默认0代表不限制。
maxmemory-samples:每次选取的带删除数据的个数。每次选取数据并不是全库扫描,而是随机选取一部分。
maxmemory-policy:逐出策略。当内存100%使用之后,对挑选出来的数据删除的策略。
策略
易丢失数据(可能会过期的数据集,server.db[*].expire)
- volatile-lru:挑选最近最少使用的数据淘汰
- volatile-lfu:挑选最佳使用次数最少的数据淘汰
- volatile-ttl:挑选将要过期的数据进行淘汰
- volatile-random:随机选择数据淘汰
检测全库数据(所有数据集,server.db[*].dict)
- alikeys-lru:挑选最近最少使用的数据淘汰
- alikeys-lfu:挑选最佳使用次数最少的数据淘汰
- alikeys-random:随机选择数据淘汰
放弃数据逐出
- no-enviction:禁止数据逐出,会引发OOM(out of memory)
策略配置在配置文件中的maxmemory-policy属性。