过期删除:
redis会将所有设置过期时间的key以及过期时间存储在字典里。
redis采取两个策略实现删除过期key:
1、定时删除:定期扫描字典,采用贪心的策略,从字典随机抽20个key,删除其中已经过期的key,如果过期的key超过1/2,那么重复上述步骤。当有大量key同时过期,为了避免无限循环扫描,这一个定时删除的任务的时间上限是25ms,但是即使有这个时间上限,仍然会出现积少成多的卡顿。(比如频繁回收内存页,定时任务每次持续25ms)。为了解决这个大量key同时过期带来的卡顿现象,应该将key的过期时间设置随机范围。这样就可以避免同时过期。
2、惰性删除:当客户访问key时,redis就会对key进行过期检查,如果过期,就会立即删除这个key。
以上删除都是默认在主线程中删除,redis4.0后可以将同步删除改成异步删除。通过命令lazyfree-lazy-expire yes开启。
懒惰删除:
redis4.0引入懒惰删除,
懒惰删除的命令是: unlink key
所谓懒惰删除就是同步线程转为异步线程。让后台线程来执行删除。
其后台删除过程主要是通过空间换时间的思想设计的:
1、首先从全局字典中移除 Key 的指针引用,此时值对象(如 String/Hash/List)仍保留在内存中,但已无任何引用路径。
2、对象移入异步队列(主线程操作)【短暂的内存占用】
3、BIO 线程从队列取出对象,执行 freeObject() 释放内存。此时才是真正的内存回收点
在这个过程中不会有线程安全问题 :
Redis 使用 原子操作(atomic) 移除全局字典的指针。当移除key的指针引用后,key会被立即删除,但是值对象仍在内存中,并且主线程无法再访问这个值对象。