阻塞分析

客户端

复杂度高的增删改查操作
1、集合全量查询和聚合操作
2、bigkey 删除
3、清空数据库

磁盘

1、AOF 日志同步写

主从节点

1、从库接收 RDB 文件后、清空数据库、加载 RDB 文件

切片集群

向其他实例传输哈希槽信息,数据迁移时遇到big key。

小结

关键路径:集合全量查询和聚合操作和从库加载 RDB 文件
非关键路径: bigkey 删除,清空数据库,以及 AOF 日志同步写。

解决方案

异步的子线程机制

Redis 主线程启动后,会使用操作系统提供的 pthread_create 函数创建 3 个子线程,分别由它们负责 AOF 日志写操作、键值对删除以及文件关闭的异步执行。主线程通过一个链表形式的任务队列和子线程进行交互。当收到键值对删除和清空数据库的操作时,主线程会把这个操作封装成一个任务,放入到任务队列中,然后给客户端返回一个完成信息,表明删除已经完成(惰性删除)。当 AOF 日志配置成 everysec 选项后,主线程会把 AOF 写日志操作封装成一个任务,也放到任务队列中。后台子线程读取任务后,开始自行写入 AOF 日志,这样主线程就不用一直等待 AOF 日志写完了。

注:异步的键值对删除和数据库清空操作是 Redis 4.0 后提供的功能。之前的版本Big key删除可以先使用集合类型提供的 SCAN 命令读取数据,然后再进行删除。因为用 SCAN 命令可以每次只读取一部分数据并进行删除,这样可以避免一次性删除大量 key 给主线程带来的阻塞。

分批读取

集合全量查询和聚合操作:可以使用 SCAN 命令,分批读取数据,再在客户端进行聚合计算

控制RBD大小

从库加载 RDB 文件:把主库的数据量大小控制在 2~4GB 左右,以保证 RDB 文件能以较快的速度加载。