过期策略:
Redis可以为所有数据结构都设置过期时间,到达过期时间时,数据被自动删除。
由于redis是单线程,频繁处理过期key,有可能造成线上读写指令卡顿。为了解决该问题,redis将设置了过期时间的key单独存放在一个独立的字典中,定时遍历这个字典删除到期的key。
主节点:
- 惰性策略:客户端访问该key时,redis对key的过期时间进行检查,如果过期,则立即删除该数据。
- 定时策略:默认每秒进行10次过期扫描,限定每次扫描最多25ms。该扫描不是普通的全量遍历,而是使用简单贪心策略
1. 从字典中随机选择20个key,
2. 删除20个key中已经过期的key
3. 如果过期key超过1/4, 这重复上诉步骤。
提问:这种方式下可能会有什么问题? 提示如果出现大量key在相同的时间过期,会导致什么问题?
从节点:
从节点不会进行定期扫描,其数据删除是被动方式的。主节点在key到期删除时,会在AOF文件中增加del指令,同步到所有从节点。从节点通过执行该指令删除过期的key。由于同步是异步进行的,所以会出现主从不一致的情况。
数据淘汰:
redis内存超出物理内存时,数据会被落盘,触发大量磁盘读取写入请求,引发redis性能急剧下降。通常情况下,为了避免该情况发生。生产环境会配置maxmemory来限制所使用的内存。
当数据量超过maxmemory时,redis会依照配置的数据淘汰策略进行数据淘汰。redis提供一下几种数据淘汰策略:(通过配置maxmemory-policy属性配置)
- noeviction: 不提供写入服务(del服务正常),读取正常。该方式为默认的淘汰策略。
- volatile-lru: 在设置了过期时间的key上, 尝试淘汰最久没有使用的key。
- allkeys-lru: 在全量key上,尝试淘汰最久没有使用的key。
- volatile-ttl:在设置了过期时间的key上,尝试淘汰剩余时间最少的key。
- volatile-random: 在设置了过期时间的key上,随机淘汰。
- allkeys-random: 在全量key上,随机淘汰。
- volatile-lfu:在设置了过期时间的key上,淘汰最少使用频率的key。(redis 4.0后支持)
- allkeys-lfu:在全量key上,淘汰最少使用频率的key。 (redis 4.0后支持)
生产环境中,如果是最为缓存,应该使用 allkeys-策略。如果是需要使用持久化功能,应该使用volatile-策略。
附录:
- 大量key同时过期,会引发什么问题?
基于redis的简单贪心算法,如果大量key同时过期,则会出现需要多次循环的情况。虽说限制了每次最多25ms,但是大量循环的话,将会导致线程卡顿,影响从客户端发过来的请求。如果此时,客户端设置的超时时间比较短,则会出现大量连接超时关闭,引发线上大量异常。此时,由于redis慢查询是指逻辑处理过程慢,不包括等待时间,因此,这种情况下的请求,无法从Redis的slowLog中看到慢查询记录。
可以通过在过期时间上加上一个随机值来进行避免。
网友评论