作者:贲绍华
爱可生研发核心工程师,负责我的项目的需要与保护工作。其余身份:柯基铲屎官。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
一、主从复制简介
Redis 主从架构下,应用默认的异步复制模式来同步数据,其特点是低提早和高性能。当 Redis master 下有多个 slave 节点,且 slave 节点无奈进行局部重同步时,slave 会申请进行全量数据同步,此时 master 须要创立 RDB 快照快照发送给 slave,从节点收到 RDB 快照到开始解析与加载。
二、主从复制风暴
在复制重建的过程中,slave 节点加载 RDB 还未实现,却因为一些起因导致失败了,slave 节点此时又会再次发动全量同步 RDB 的申请,周而复始。当多个 slave 节点同时循环申请时,导致了复制风暴的呈现。
三、问题景象
3.1 CPU:
master 节点会异步生成 RDB 快照,数据量十分大时 fork 子过程十分耗时,同时 CPU 会飙升,且会影响业务失常响应。
3.2 磁盘:
从 Redis 2.8.18 版本开始,反对无磁盘复制,异步生成的 RDB 快照将在子过程中间接发送 RDB 快照至 slave 节点,多个 slave 节点共享同一份快照。所以磁盘 IO 并不会出现异常。
3.3 内存与网络:
因为 RDB 是在内存中创立与发送,当复制风暴发动时,master 节点创立 RDB 快照后会向多个 slave 节点进行发送,可能使 master 节点内存与网络带宽耗费重大,造成主节点的提早变大,极其状况会产生主从节点之间连贯断开,导致复制失败。slave 节点在失败重连后再次发动新一轮的全量复制申请,陷入恶性循环。
四、呈现的场景
- 单 master 节点(主机上只有一台 redis 实例)当机器产生故障导致网络中断或重启复原时。
- 多 master 节点在同一台机器上,当机器产生故障导致网络中断或重启复原时。
- 大量 slave 节点同时重启复原。
- 复制缓冲区过小,缓冲区的下限是由 client-output-buffer-limit 配置项决定的,当 slave 还在复原 RDB 快照时,master 节点继续产生数据,缓冲区如果被写满了,会导致 slave 节点连贯断开,再次发动重建复制申请。发动全量复制 -> 复制缓冲区溢出 -> 连贯中断 -> 重连 -> 发动全量复制 -> 复制缓冲区溢出 -> 连贯中断 -> 重连 …
- 网络长时间中断导致的连贯异样:跨机房、跨云、DNS 解析异样等导致的主从节点之间连贯失落。主从节点判断超时(触发了 repl-timeout),且失落的数据过多,超过了复制积压缓冲区所能存储的范畴。
- 数据量过大,生成 RDB 快照的 fork 子过程操作耗时过长,导致 slave 节点长时间收不到数据而触发超时,此时 slave 节点会重连 master 节点,再次申请进行全量复制,再次超时,再次重连。
五、解决方案
5.1 升高存储下限
Redis 实例的存储数据的下限不要过大,过高的状况下会影响 RDB 落盘速度、向 slave 节点发送速度、slave 节点复原速度。
5.2 复制缓冲区调整
master 节点 client-output-buffer-limit 配置项阈值增大(或调整为不限度),repl_timeout 配置项阈值增大。使 slave 节点有足够的时候复原 RDB 快照并且不会被动断开连接。
5.3 部署形式调整
单个主机节点内尽量不再部署多个 master 节点,避免主机因为意外状况导致的所有 slave 节点的全量同步申请发送至同一主机内。
5.4 架构调整
缩小 slave 节点个数。或调整 slave 架构层级,在 Redis 4.0 版本之后,sub-slave 订阅 slave 时将会收到与 master 一样的复制数据流。