文章目录


Redis进阶-Redis的惰性删除_异步线程


Pre

​Redis进阶-Redis对于过期键的三种清除策略​

我们一直说 Redis 是单线程的,这里的我们默认指的都是Redis主要的工作线程,面向开发的。 实际上 Redis 内部实并不是只有一个主线程,它有很多个异步线程专门用来处理一些耗时的操作


del ------> unlink

删除指令 del 会直接释放对象的内存,大部分情况下,这个指令非常快,没有明显延迟。不过如果删除的 key 是一个非常大的对象,举个例子一个包含几千万元素的key,那么删除操作就会导致单线程卡顿。

Redis 为了解决这个卡顿问题,在 4.0 版本引入了 ​unlink​ 指令,它能对删除操作进行懒处理,丢给后台线程来异步回收内存。

192.168.18.131:8001> set artisan vv
-> Redirected to slot [4009] located at 192.168.18.133:8006
OK
192.168.18.133:8006> UNLINK artisan
(integer) 1
192.168.18.133:8006> UNLINK artisan
(integer) 0
192.168.18.133:8006>

FLUSHDB/FLUSHALL --> FLUSHDB ASYNC/FLUSHALL ASYNC

Redis 提供了 flushdb 和 flushall 指令,用来清空数据库,当数据量很大时,容易阻塞Redis。

Redis 4.0 同样给这两个指令也带来了异步化,在指令后面增加 ​async​ 参数扔给后台线程销毁,不会阻塞当前线程。

192.168.18.133:8006> FLUSHDB ASYNC
OK
192.168.18.133:8006> FLUSHALL ASYNC
OK
192.168.18.133:8006>

异步队列

主线程将对象的引用从「大树」中摘除后,会将这个 key 的内存回收操作包装成一个任务,塞进异步任务队列,后台线程会从这个异步队列中取任务。

任务队列被主线程和异步线程同时操作,所以必须是一个线程安全的队列。

Redis进阶-Redis的惰性删除_异步线程_02

不是所有的 unlink 操作都会延后处理,如果对应 key 所占用的内存很小,延后处理就没有必要了,这时候 Redis 会将对应的 key 内存立即回收,跟 del 指令一样。


AOF Sync

Redis 需要每秒一次(可配置)同步 AOF 日志到磁盘,确保消息尽量不丢失,需要调用

sync 函数,这个操作会比较耗时,会导致主线程的效率下降,所以 Redis 也将这个操作移到异步线程来完成。

执行 AOF Sync 操作的线程是一个独立的异步线程,和前面的懒惰删除线程不是一个线程,同样它也有一个属于自己的任务队列,队列里只用来存放 AOF Sync 任务

redis 4.0这次除了显示增加unlink、flushdb async、flushall async命令之外,还增加了4个后台删除配置项,分别为:

  • slave-lazy-flush:slave接收完RDB文件后清空数据选项
  • lazyfree-lazy-eviction:内存满逐出选项
  • lazyfree-lazy-expire:过期key删除选项
  • lazyfree-lazy-server-del:内部删除选项,比如rename srckey destkey时,如果destkey存在需要先删除destkey

以上4个选项默认为同步删除,可以通过​config set [parameter] yes​打开后台删除功能。