删除指令del会直接释放对象的内存,大部分情况下,这个指令非常快,没有明显延迟。如果删除的key是一个非常大的对象,那么删除操作就会导致单线程卡顿。
为了解决这个卡顿问题,在4.0版本引入了unlink指令,它能对删除操作进行懒处理,丢给后台线程来异步回收内存(看来Redis还有几个线程来专门做删除操作)。
Redis提供了flushdb、flushall指令,用来清空数据库,这也是极其缓慢的操作。4.0同样给这两个指令也带来了异步化,在指令后面增加async参数就可以扔给后台线程慢慢清空数据库。
问题:删除线程工作内容如下:
第一步:主线程将对象的引用删除后,将这个key的内存回收操作包装成一个任务,塞进异步任务队列,后台线程会从这个异步队列中取任务。任务队列被主线程和异步线程同时操作,所以必须是一个线程安全的队列。
注意:不是所有的unlink操作都会延后处理,如果对应key所占用的内存很小,Redis会将对应的key内存立即回收。
问题:Redis除了删除子线程,还有其他子线程吗?
答:Redis需要每秒一次(可配置)同步AOF日志到磁盘,确保消息尽量不丢失,需要调用sync函数,这个操作会比较耗时,会导致主线程的效率下降,所以Redis也将这个操作移到异步线程来完成。执行AOF Sync操作的线程是一个独立的异步线程,和前面的懒惰删除线程不是一个线程,同样它也有一个属于自己的任务队列,队列里只用来存放AOF Sync任务。
Redis4.0 为这些删除点也带来了异步删除机制,打开这些点需要额外的配置选项。
slave-lazy-flush从库接受完rdb文件后的flush操作
lazyfree-lazy-eviction内存达到maxmemory时进行淘汰
lazyfree-lazy-expire key过期删除
lazyfree-lazy-server-del rename指令删除destKey