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 以后支持 “增量同步”,主库将断连期间的命令发送给从库,继续实现主从同步。

具体请看:

Redis 主从同步

2. 复制缓冲区

(1) 什么是复制缓冲区?

主节点会为每一个从节点维护一个复制缓冲区,用于存储 “所有数据的同步” 过程中的 “新写命令”。

(2) 单个复制缓冲区溢出

如果 “所有数据的同步” 执行较慢,且主节点在这一过程中接收了大量的新写命令,新写命令将在复制缓冲区中堆积,并最终导致溢出。如果发生溢出,则主节点会直接关闭和从节点的复制操作,使同步失败。

为避免复制缓冲区溢出,可以:

  • 控制主节点的数据量

    一般而言,将主节点的数据量控制在 2 ~ 4 GB,这样可以避免 “所有数据的同步” 执行时间过长

  • 设置复制缓冲区的大小

    1
    client-output-buffer-limit slave 512mb 128mb 60

    通过这种设置,使得复制缓冲区可以累积 512K 条命令,且每秒最多写入 2K 条

(3) 所有复制缓冲区溢出

主节点会为每个从节点维护一个复制缓冲区,因此主节点上复制缓冲区的内存开销是所有复制缓冲区的总和。

为了避免复制缓冲区造成较大的内存开销,应该控制从节点的个数,避免搭建大规模的主从集群。

3. 复制积压缓冲区

复制积压缓冲区用于主从重连时的 “增量同步”。

由于复制积压缓冲区是一个大小有限的环形缓冲区,因此不会发生溢出情况,可以酌情调整复制积压缓冲区的大小,避免因旧数据被覆盖导致断连后需要重新同步的情况。

参考