redis过期删除
redis的键可以设置过期时间,但是并不是每个键一到过期时间就会立即删除,redis不可能给每个设置过期时间的key上添加一个定时器来监视是否过期,CPU根本承受不了如此多的定时线程
注意:我使用的版本是6.0.10,不同版本可能略有差别
删除策略
存在的删除策略:
- 定时删除 在设置键的同时创建定时器,过期时间到了就执行对键的删除,这种策略对内存使用率有优势,但是占用CPU资源太多
- 定期删除 每隔特定时间对数据库进行一次扫描,检测并删除其中过期的键值对
- 惰性删除 键值对过期暂时不进行删除,当获取键时先查看是否已经过期,过期则进行删除,这种策略可能会由于一些过期key一直没有被访问,浪费一定的内存
redis采用的策略是定期删除+惰性删除
定期删除是指每隔一段时间去检查是否有过期的key,如果有则删除
惰性删除是指在获取key的时候检查一下这个key是否过期
定期删除的配置是hz(默认是10,即每秒十次扫描)
首先客户端在尝试访问某个key的时候,redis会检查是否过期,如果过期则删除,但是有些key是不会被访问到的,redis的定期删除则会进行扫描并删除过期的key
- 从过期字典里随机抽取20个key
- 删除这20个key中已经过期的key
- 如果过期的比例超过25%,则重复步骤一
过期的key过多会导致循环抽取删除,为防止过度循环,增加了扫描时间的上限,默认不超过25ms
应该避免同一时刻大量key同时过期
在主从结构中,从服务器就算读取到过期键也不会删除,只有接收到主服务器发来的del命令之后才会删除
淘汰机制
配置最大内存的大小,如果超过该内存大小,就会使用淘汰机制进行淘汰
maxmemory 100mb
也可以通过命令进行修改
127.0.0.1:6380> config set maxmemory 50mb
OK
127.0.0.1:6380> config get maxmemory
1) "maxmemory"
2) "52428800"
由于使用定期删除+惰性删除机制,但是也可能很多过期的没有被删除掉导致内存不足的情况,所以redis存在淘汰机制
- volatile-lru -> Evict using approximated LRU, only keys with an expire set 当内存不足时,设置了过期时间的键,选取最近最少使用的键抛弃(Least Recently Used)
- allkeys-lru -> Evict any key using approximated LRU 当内存不足时,对于所有的键,选取最近最少使用的键抛弃(Least Recently Used)
- volatile-lfu -> Evict using approximated LFU, only keys with an expire set 当内存不足时,设置了过期时间的键,选取最少频率使用的键抛弃(Least Frequently Used)
- allkeys-lfu -> Evict any key using approximated LFU 当内存不足时,对于所有的键,选取最少频率使用的键抛弃(Least Frequently Used)
- volatile-random -> Remove a random key having an expire set 当内存不足时,对于设置过期时间的键,随机选取键抛弃
- allkeys-random -> Remove a random key, any key 当内存不足时,对于所有的键,随机选取键抛弃
- volatile-ttl -> Remove the key with the nearest expire time (minor TTL) 当内存不足时,抛弃最近要过期的键
- noeviction -> Don’t evict anything, just return an error on write operations 默认策略,不淘汰,如果内存已满,写操作返回错误
在使用volatile-lfu、volatile-random、volatile-ttl时,如果没有key可以淘汰,则与noeviction一样在写操作时返回错误
获取当前的内存策略
config get maxmemory-policy
可以在配置文件修改
maxmemory-policy noeviction
也可以使用命令设置
config set maxmemory-policy noeviction
在进行LRU/LFU/TTL淘汰策略时,并不是那么准确,可以通过采样率来进行设置其准确度,默认是5,即随机选出5个key,然后淘汰掉里面最近最少使用的key。
当设置为10的时候就非常接近真正的LRU算法了,但是会消耗更多的CPU,5已经是足够好的结果了
maxmemory-samples 5
参考文献