Redis采用的是定期删除 + 懒惰删除策略.
Redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,默认每 100ms 进行一次过期扫描:
从库不会进行过期扫描,从库对过期的处理是被动的.主库在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步到所有的从库,从库通过执行这条 del 指令来删除过期的 key.因为指令同步是异步进行的,所以主库过期的 key 的 del 指令没有及时同步到从库的话,会出现主从数据的不一致,主库没有的数据在从库里还存在.
unlink 指令,它能对删除操作进行懒处理,丢给后台线程来异步回收内存.
>?unlink?key
>?flushall?async
主线程将对象的引用从「大树」中摘除后,会将这个 key 的内存回收操作包装成一个任务,塞进异步任务队列,后台线程会从这个异步队列中取任务.任务队列被主线程和异步线程同时操作,所以必须是一个线程安全的队列.不是所有的 unlink 操作都会延后处理,如果对应 key 所占用的内存很小,延后处理就没有必要了,这时候 Redis 会将对应的 key 内存立即回收,跟 del 指令一样.
slave-lazy-flush 从库接受完 rdb 文件后的 flush 操作
lazyfree-lazy-eviction 内存达到 maxmemory 时进行淘汰
lazyfree-lazy-expire key 过期删除
lazyfree-lazy-server-del rename 指令删除 destKey
Redis 的内存占用会越来越高.Redis 为了限制最大使用内存,提供了 redis.conf 中的配置参数 maxmemory.当内存超出 maxmemory,Redis 提供了几种内存淘汰机制让用户选择,配置 maxmemory-policy:
noeviction:当内存超出 maxmemory,写入请求会报错,但是删除和读请求可以继续.(使用这个策略,疯了吧)
allkeys-lru:当内存超出 maxmemory,在所有的 key 中,移除最少使用的key.只把 Redis 既当缓存是使用这种策略.(推荐).
allkeys-random:当内存超出 maxmemory,在所有的 key 中,随机移除某个 key.(应该没人用吧)
volatile-lru:当内存超出 maxmemory,在设置了过期时间 key 的字典中,移除最少使用的 key.把 Redis 既当缓存,又做持久化的时候使用这种策略.
volatile-random:当内存超出 maxmemory,在设置了过期时间 key 的字典中,随机移除某个key.
volatile-ttl:当内存超出 maxmemory,在设置了过期时间 key 的字典中,优先移除 ttl 小的.
实现 LRU 算法除了需要 key/value 字典外,还需要附加一个链表,链表中的元素按照一定的顺序进行排列.当空间满的时候,会踢掉手机号购买平台地图链表尾部的元素.当字典的某个元素被访问时,它在链表中的位置会被移动到表头.所以链表的元素排列顺序就是元素最近被访问的时间顺序.使用 Python 的 OrderedDict(双向链表 + 字典) 来实现一个简单的 LRU 算法:
from?collections?import?OrderedDict class?LRUDict(OrderedDict): ?def?__init__(self,?capacity): ??self.capacity?=?capacity ??self.items?=?OrderedDict() ?def?__setitem__(self,?key,?value): ??old_value?=?self.items.get(key) ??if?old_value?is?not?None: ??self.items.pop(key) ??self.items[key]?=?value ??elif?len(self.items)? ??self.items[key]?=?value ??else: ??self.items.popitem(last=True) ??self.items[key]?=?value ?def?__getitem__(self,?key): ??value?=?self.items.get(key) ??if?value?is?not?None: ??self.items.pop(key) ??self.items[key]?=?value ??return?value ?def?__repr__(self): ??return?repr(self.items) d?=?LRUDict(10) for?i?in?range(15): ?d[i]?=?i
//?redis?的对象头 typedef?struct?redisObject?{ ?unsigned?type:4;?//?对象类型如?zset/set/hash?等等 ?unsigned?encoding:4;?//?对象编码如?ziplist/intset/skiplist?等等 ?unsigned?lru:24;?//?对象的「热度」 ?int?refcount;?//?引用计数 ?void?*ptr;?//?对象的?body
以上就是土嘎嘎小编为大家整理的谈谈 Redis 的过期策略相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!