Redis 缓冲区溢出问题总结
# Redis 缓冲区溢出问题总结
# 1. 缓冲区应用场景
客户端和服务端通信
分为客户端的输入缓冲区和输出缓冲区
普通客户端
订阅客户端
主从客户端
主从数据同步
- 全量复制下的复制缓冲区(本质上是一个和从节点连接的客户端)
- 增量复制下的复制积压缓冲区(用于网络闪断后的写命令同步恢复)
# 2. 缓冲区溢出对 Redis 的影响
- 引起网络连接关闭
- 导致客户端与服务端的连接关闭,造成业务停摆
- 导致主从之间的连接关闭,造成主从全量同步命令失败,需要重新执行
- 引起命令数据丢失
- 主节点的复制积压缓冲区属于环形缓冲区,一旦溢出,新写入的命令就会覆盖旧的命令数据,造成命令数据的丢失,进而导致从节点需要重新执行全量复制。
# 3. 缓冲区溢出的主要原因以及对应解决方案
命令数据发送过快过大
- 对于普通客户端来说,要避免 big key,避免在线上生产环境执行 MONITOR 命令(持续占用输出缓冲区)
- 对于复制缓冲区来说,要避免过大的 RDB 文件传输
命令数据处理较慢
- 要减少 Redis 主线程上的阻塞操作,例如可以使用异步的删除操作等方式,像 UNLINK 等
缓冲区空间问题
- 可以通过参数 client-output-buffer-limit 来设置合理的输出缓冲区,复制缓冲区和复制积压缓冲区大小。需要注意的是,输入缓冲区大小默认是固定的,只能通过源码来进行修改
# 4. 一些额外注意点
可以使用
CLIENT LIST
命令来查询每个客户端对输入缓冲区的使用情况参数 client-output-buffer-limit 的设置包括两方面
- 设置输出缓冲区大小的上限阈值
- 设置输出缓冲区持续写入数据的数量上限阈值 和 持续写入数据的时间上限阈值
给普通客户端设置输出缓冲区大小时,一般都默认为 0,因为普通客户端往往是阻塞式发送数据,一般只需要避免特别大的 bigkey 就行了;而订阅客户端是非阻塞式发送,需要合理设置参数
为了加快 RDB 文件的传输 和 避免复制缓冲区积累过多命令,一般把主节点的数据量控制在 2 - 4 GB 左右
redis 实例会有一个 maxmemory 配置项,超过 maxmemory 后会导致淘汰数据。
- 主库上的从库输出缓冲区不计算在 Redis 的使用内存中,只计入了普通客户端和订阅客户端的输出缓冲区
主节点上复制缓冲区的内存开销是每个从节点客户端对应主节点上的输出缓冲区占用内存的总和,因此需要控制从节点的数量,以及设置合理的缓冲区大小
除了服务端上有缓冲区,客户端中也有缓冲区,例如:Pipeline、操作系统的网络缓冲区。通过一次性批量地发送写入数据,可以减少网络 IO 次数,降低延迟,提高访问性能。
Last Updated: 9/2/2023, 2:52:50 PM