Redis 堵塞式操作
本文将介绍 Redis 中的堵塞式操作。
一、交互点
Redis 实例在运行时,需要和许多对象进行交互,这些交互点往往会发生阻塞。
列举交互点如下:
- 客户端:
- 网络 IO
- 键值对增删改查操作
- 数据库操作
- 磁盘:
- 生成 RDB 快照
- 记录 AOF 日志
- AOF 日志重写
- 主从节点:
- 主库生成
- 传输 RDB 文件
- 从库接收 RDB 文件
- 清空数据库
- 加载 RDB 文件
- 切片集群实例:
- 向其它实例传输哈希槽信息、数据传输
二、堵塞式操作
1. 客户端交互 - 网络 IO
Redis 使用了 IO 多路复用机制,避免了堵塞处理网络请求。因此,网络 IO 不是导致 Redis 堵塞的原因。
2. 客户端交互 - 键值对增删改查
复杂度高的命令:在 Redis 中,集合全量查询和聚合操作的操作复杂度为 O(N),会导致堵塞
大键值对的删除:在 Redis 中,大集合的删除操作会导致堵塞
删除的本质是释放键值对占用的内存空间。对于操作系统来说,为了更加高效地管理内存空间,在应用程序释放内存时,需要把释放掉的内存块插入空闲内存块链表中,以便后续进行管理和再分配。这个过程需要一定时间,并且会堵塞当前应用程序。
Redis 4.0 提供了
UNLINK
命令用于异步删除键值对
3. 客户端交互 - 数据库操作
清空数据库涉及到删除和释放所有的键值对,因此可能和 “客户端交互 - 键值对增删改查 - 大键值对的删除” 一样导致堵塞。
Redis 4.0 提供了
SLUSHALL ASYNC
命令用于异步清空数据库
4. 磁盘交互
Redis 支持非堵塞式生成 RDB 快照、记录 AOF 日志和 AOF 日志重写,但其中的 fork()
操作也会堵塞主线程。
5. 主从集群交互 - 加载 RDB
对于从库而言,需要首先清空当前数据库,该操作是 “客户端交互 - 数据库操作 - 清空数据库”,会导致堵塞。
此外,加载 RDB 时需要将其加载到内存中,这个过程的快慢和 RDB 文件的大小相关,会造成主线程堵塞。
6. 切片集群交互 - 数据迁移
Redis Cluster 使用了同步迁移的方案,如果迁移大键值对,会造成主线程堵塞。
参考
- Redis
- Redis 教程 | 菜鸟教程
- Redis数据库学习教程(快速入门版)
- Redis 核心技术与实战