一、Redis过期策略
redis通常被用来当作缓存 使用,虽然它也可以用作数据库 和消息队列,但是数据库方面,redis相较于Mysql,Hbase,Oracle等数据库又逊色了很多;消息队列方面,又没有RabbitMQ等消息队列功能更完善,程序员们肯定会选择更优秀的工具。
由于是缓存,那redis中存储的数据通常是不固定的,通常会给数据的键值对设置过期时间,从而能够适当地释放redis的存储空间,那么redis是如何设置过期时间的呢?
redis的过期策略是:惰性删除 + 定期删除
1.1 惰性删除
所谓惰性删除,字面意思就是redis很懒惰,当一个键值对达到过期时间后,不会立即删除,而是当下一次访问到该Key时,发现过期,再删除该键值对。
- 当已过期,删除key,返回nil;
- 当未过期,返回对应的value值;
- 执行所有读写命令之前,先调用redis内部的expireIfNeed函数判断是否过期。
惰性删除的好处 是cpu消耗极少,只需要在访问过期的key值之后,再进行删除逻辑。
但其弊端 也很明显---易形成僵尸数据。就是如果不访问已过期的key值,就不管,任其存在于redis内存中占用资源空间,这就是僵尸数据。我们都知道redis作为缓存来说,其内存是很宝贵的,如果只使用惰性删除会导致内存空间不足的问题。

1.2 定期删除
所谓定期删除,是指redis会每隔100ms扫描设置了过期时间的键空间中以及过期的键值对,并删除过期的key。
假设redis中存储了10w+设置了过期时间的数据,每一次扫描所有的key来查找已过期的key,不到下一次扫描,redis就以及瘫痪掉了,因为数据量太大,如果每隔100ms就扫描所有的key,cpu全消耗在扫描key值上了。所以此处说的定期扫描,是每隔100ms对键空间中的部分数据进行扫描 ,而不是全部。
redis综合使用惰性删除和定期删除,就能够解决大部分已过期数据的删除,因为显然,定期删除部分过期数据和当访问才删除不一定能清理掉所有的过期数据。那随着存储的数据越来越多,redis存储内存肯定会在某一刻被填满,此时该怎样释放空间呢?
答案是:内存淘汰机制。
二、内存淘汰机制
内存淘汰机制,实际上是redis过期策略的兜底策略,由于惰性删除和定期删除会残留部分key,当redis占用内存达到最大值,就会触发内存淘汰机制,主要策略有以下几种:
- noeviction :当内存占满,有新的数据需要写入时,直接报错拒绝。(默认策略,最不推荐)
- allkeys-lru:在全部key中,删除最近最少使用的key。(使用频率最高)
- allkeys-lfu:在全部key中,删除使用频率最低的key。
- allkeys-random:在全部key中,随机删除。
- volatile-lru:在过期key中,删除最近最少使用的key。
- volitaile-lfu:在全部key中,删除使用频率最低的key。
- volitaile-random:在过期key中,随机删除。
- volatile-ttl:在过期key中,优先删除存货时间最短的。
三、完整工作流程总结
- 使用 SET key value EX seconds 给key设置过期时间;
- key过期时间到了,但不会立即删除;
- 当用户访问key时,删除key;
- redis每隔100ms对部分过期的key进行删除;
- 当redis存储内存被占满,触发内存淘汰机制。
本片文章讨论了关于redis过期策略的知识,希望可以对大家学习redis有所帮助,如有表述错误,希望指点。