异步机制:如何避免单线程模型的阻塞

93 阅读2分钟

阻塞点

image.png
  1. 和客户端交互时的阻塞点 复杂度高的增删改查操作会阻塞 Redis。比如:集合全量查询和聚合操作,bigkey删除操作,清空数据库。

  2. 和磁盘交互时的阻塞点 Redis 直接记录 AOF 日志时,会根据不同的写回策略对数据做落盘保存。一个同步写磁盘的操作的耗时大约是 1~2ms,如果有大量的写操作需要记录在 AOF 日志中,并同步写回的话,就会阻塞主线程了。这就得到了 Redis 的第四个阻塞点了:AOF 日志同步写。

  3. 主从节点交互时的阻塞点 加载 RDB 文件就成为了 Redis 的第五个阻塞点。

  4. 切片集群实例交互时的阻塞点 如果你使用了 Redis Cluster 方案,而且同时正好迁移的是 bigkey 的话,就会造成主线程的阻塞,因为 Redis Cluster 使用了同步迁移。

哪些阻塞点可以异步执行

如果一个操作能被异步执行,就意味着,它并不是 Redis 主线程的关键路径上的操作。我再解释下关键路径上的操作是啥。这就是说,客户端把请求发送给 Redis 后,等着 Redis 返回数据结果的操作。

对于 Redis 的五大阻塞点来说,除了“集合全量查询和聚合操作”和“从库加载 RDB 文件”,其他三个阻塞点涉及的操作都不在关键路径上,所以,我们可以使用 Redis 的异步子线程机制来实现 bigkey 删除,清空数据库,以及 AOF 日志同步写。

异步的子线程机制

当收到键值对删除和清空数据库的操作时,主线程会把这个操作封装成一个任务,放入到任务队列中,然后给客户端返回一个完成信息,表明删除已经完成。但实际上,这个时候删除还没有执行,等到后台子线程从任务队列中读取任务后,才开始实际删除键值对,并释放相应的内存空间。

和惰性删除类似,当 AOF 日志配置成 everysec 选项后,主线程会把 AOF 写日志操作封装成一个任务,也放到任务队列中。后台子线程读取任务后,开始自行写入 AOF 日志,这样主线程就不用一直等待 AOF 日志写完了。

image.png

键值对删除:unlink 清空数据库:可以在 FLUSHDB 和 FLUSHALL 命令后加上 ASYNC


此文章为8月Day11学习笔记,内容来源于极客时间《redis核心技术与实战》