场景
使用del指令删除key时,redis会直接释放对象的内存,当对象很小时这个指令速度是很快的,但是如果是一个很大的对象被del时,那么删除操作就会比较耗时,造成其他指令阻塞,对客户端造成卡顿的现象。
unlink
Redis在4.0版本中引入了unlink指令,可以对删除操作进行懒处理,丢给后台线程异步回收内存。
unlink youkey
注意,虽然是异步删除,但并不会引发并发问题,因为unlink指令发出后,该key将从redis有效数据结构中移除,其他线程无法再获取到它。
flush
redis提供了 flushdb 和 flushall 用于清空数据库,清空整个redis db也是一个非常耗时的操作,在4.0版本中,在指令后面增加一个 async 参数就可以进行异步的清空了。
flushall async
异步队列
异步删除的操作一般会被放到一个异步队列中,后台线程会从这个队列中取任务进行删除处理,该队列同时被主线程和异步线程同时操作,因此是一个线程安全的队列。
不过不是所有的 unlink 操作都会延后处理,如果要操作的对象占用内存较小,就没必要丢到异步队列中处理了,而是直接删除回收内存。
AOF Sync
AOF日志sync到磁盘也是一个很慢的操作,为了减少因为宕机导致的数据丢失,Redis一般1s(可配置)同步一次,这个操作会导致主线程效率下降,
因此AOF Sync操作也被放到异步线程中操作,执行Sync操作的线程是一个独立的线程,和懒惰删除的线程不是一个,Sync异步线程拥有一个自己的任务队列,队列里只存放AOF Sync任务。
其他异步删除点
除del与flush操作外,Redis在key的过期、LRU淘汰、rename指令过程中,都会实施内存回收,还有一种特殊操作,
即发生于正在进行全量同步的从节点中,在接受完整的rdb文件之后,也需要将当前内存一次性清空,随后加载rdb文件进行内容恢复。
在redis4.0中打开如下选项可对这些删除点进行异步操作的支持:
- slave-lazy-flush:从节点接收完毕rdb后进行异步flush
- lazyfree-lazy-eviction:执行LRU淘汰时异步删除
- lazyfree-lazy-expire:key过期时异步删除
- lazyfree-lazy-server-del:rename删除destkey异步执行