Redis 缓冲区
本文将介绍 Redis 中的缓冲区。
一、什么是缓冲区?
缓冲区是一块用于存放命令的内存空间,它能够避免因为处理速度慢于命令发送速度而导致的异常问题。
二、客户端输入输出缓冲区
1. 说明
客户端输入输出缓冲区并不在客户端,而是在服务端,是服务端针对每个客户端设置的缓冲区
服务端为每个连接的客户端设置了一个输入缓冲区和输出缓冲区,称为客户端输入缓冲区和输出缓冲区。
2. 客户端输入缓冲区
(1) 什么是客户端输入缓冲区?
客户端输入缓冲区会把客户端发送过来的命令暂存,Redis 主线程从输入缓冲区中读取命令并处理。
(2) 单个客户端输入缓冲区溢出
可能导致单个客户端输入缓冲区溢出的情况是:
- 写入大集合数据
- 服务端处理请求的速度过慢,导致命令在缓冲区中堆积
并且,客户端输入缓冲区的大小被写死在代码中,固定为 1GB。
如果发生溢出的情况,Redis 的处理方法是将客户端连接关闭,这将导致业务程序无法进行数据存取。
(3) 所有客户端输入缓冲区溢出
通常情况下,Redis 服务端会服务于多个客户端,因此可能需要同时维护多个客户端输入缓冲区。
这些缓冲区将会和数据区、其它缓冲区一起共享 Redis 的内存空间,如果占用过多空间,将会影响数据的存储,甚至引起 Redis 崩溃。
又由于 Redis 并未提供调整客户端输入缓冲区大小的机制,因此只能通过避免写入大集合数据、避免主线程堵塞影响请求处理的方式解决。
3. 客户端输出缓冲区
(1) 什么是客户端输出缓冲区?
客户端输出缓冲区会将 Redis 要返回给客户端的数据暂存。
客户端输出缓冲区分为两个部分:
- 固定缓冲区:大小为 16KB;暂存成功信息和错误信息
- 动态缓冲区:大小可以动态改变;用于存储数据信息
(2) 客户端输出缓冲区溢出
可能导致客户端输出缓冲区溢出的情况有:
客户端返回了大集合数据
执行了 MONITOR 命令对 Redis 进行监控
MONITOR 命令会检测 Redis 的执行,持续地将命令输出到输出缓冲区中
缓冲区大小设置不合理
客户端输出缓冲区允许在配置文件中进行配置,如下:
1
client-output-buffer-limit 缓冲区类型 大小限制 持续写入量限制 持续写入时间限制
对于普通客户端,一般设置为
client-output-buffer-limit normal 0 0 0
,即不做任何限制因为普通客户端会堵塞式发送请求(发送一个请求,等待获取响应后,再发送第二个请求),这种情况下不会造成堵塞,因此不做限制
对于订阅客户端,一般设置为
client-output-buffer-limit pubsub 8mb 2mb 60
因为一旦频道有消息,服务端都会将消息放入客户端输出缓冲区中,可能会产生堵塞的情况
三、主从集群中的缓冲区
1. 主从同步的流程
如果是初次同步,会首先进行 “所有数据的同步”,然后进行前一步执行过程中 “新写命令的同步”,最后通过网络连接进行 “持续同步”。
如果已同步且发生断连,Redis 2.8 以后支持 “增量同步”,主库将断连期间的命令发送给从库,继续实现主从同步。
具体请看:
2. 复制缓冲区
(1) 什么是复制缓冲区?
主节点会为每一个从节点维护一个复制缓冲区,用于存储 “所有数据的同步” 过程中的 “新写命令”。
(2) 单个复制缓冲区溢出
如果 “所有数据的同步” 执行较慢,且主节点在这一过程中接收了大量的新写命令,新写命令将在复制缓冲区中堆积,并最终导致溢出。如果发生溢出,则主节点会直接关闭和从节点的复制操作,使同步失败。
为避免复制缓冲区溢出,可以:
控制主节点的数据量
一般而言,将主节点的数据量控制在 2 ~ 4 GB,这样可以避免 “所有数据的同步” 执行时间过长
设置复制缓冲区的大小
1
client-output-buffer-limit slave 512mb 128mb 60
通过这种设置,使得复制缓冲区可以累积 512K 条命令,且每秒最多写入 2K 条
(3) 所有复制缓冲区溢出
主节点会为每个从节点维护一个复制缓冲区,因此主节点上复制缓冲区的内存开销是所有复制缓冲区的总和。
为了避免复制缓冲区造成较大的内存开销,应该控制从节点的个数,避免搭建大规模的主从集群。
3. 复制积压缓冲区
复制积压缓冲区用于主从重连时的 “增量同步”。
由于复制积压缓冲区是一个大小有限的环形缓冲区,因此不会发生溢出情况,可以酌情调整复制积压缓冲区的大小,避免因旧数据被覆盖导致断连后需要重新同步的情况。
参考
- Redis
- Redis 教程 | 菜鸟教程
- Redis数据库学习教程(快速入门版)
- Redis 核心技术与实战