Redis 阻塞式操作

2021/01/27 posted in  性能

Redis的网络IO和键值对的读写都是由主线程完成的,如果主线程操作消耗时间太长,就会引起主线程阻塞。

Redis实例的阻塞点

  1. 客户端:网络IO,键值对增删改操作,数据库操作
  2. 磁盘:生成RDB快照,记录AOF日志,AOF重写
  3. 主从节点:主库生成,传输RDB文件,从库接受RDB文件、清空数据库、加载RDB 文件
  4. 切片集群实例:向其他实例传输哈希槽信息,数据迁移

汇总

客户端交互的阻塞点

  1. 集合全量查询和聚合操作
    • 复杂度为O(N) 的操作都会阻塞
  2. bigkey 删除操作
    • 删除操作会释放内存,而释放的内存会插入到一个空闲内存块表中,这个过程会阻塞释放内存的进程
  3. 清空数据库
    • 删除键值都有阻塞风险那么删除数据库就更是有阻塞风险了

磁盘交互阻塞点

Redis 设计采用子进程进行RDB 文件生成,以及AOF 日志重写这样慢速的磁盘IO就不会阻塞主进程

  1. AOF日志同步写:一个同步写磁盘操作耗时1~2ms ,如果有大量的写操作记录在AOF日志中,并同步回写的话,就会阻塞主线程

主从节点交互阻塞点

  1. 加载RDB文件:清空当前数据库后,还需要RDB文件加载到内存中,如果RDB文件大,加载过程慢


切片集群实例交互时的阻塞点

使用Redis Cluster 方案,在迁移过程中有bigkey 的话,会造成组线程阻塞,因为Redis Cluster 使用了同步迁移





可以异步的阻塞点

针对5个阻塞点,除了全量查询和聚合操作 和 从库加载RDB 文件,其他三个阻塞点都可以使用异步子线程机制实现 bigkey 删除、清空数据库、AOF日志同步写

异步子线程机制

Redis 主线程启动后,会调用操作系统提供过的pthread_create 创建3个子线程,分别负责AOF日志写操作、键值对删除、文件关闭的异步执行

4.0 之后异步删键值对和数据库的清空操作

  1. UNLINK 删除大量元素
  2. FLUSHDB 和 FLUSHALL 加ASYNC 可以异步执行