前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >redis8.0新特性之Rdb Channel Replication:如何使复制过程更快,提升主节点在全量同步期间的性能

redis8.0新特性之Rdb Channel Replication:如何使复制过程更快,提升主节点在全量同步期间的性能

作者头像
崔认知
发布2025-03-03 12:55:08
发布2025-03-03 12:55:08
4600
代码可运行
举报
文章被收录于专栏:nobodynobody
运行总次数:0
代码可运行

redis 8.0-M03版本提供了RDB 通道复制功能

水平及维护精力所限,译文不免存在错误或过时之处,如有疑问,请查阅原文(文末英文链接)。

动机

全量同步期间,当主节点向从节点传递 RDB 文件时传入的写命令会被暂存在复制缓冲区中,以便在 RDB文件 传输完成后发送给从节点。如果 RDB文件传输耗时过长,可能会给主节点带来内存压力。此外,一旦从节点连接累积的复制数据超过了输出缓冲区的限制,主节点将断开与从节点的连接。这可能会导致复制失败。

RDB 通道复制的主要优势在于在传输 RDB文件的同时并行传输传入写命令。这种方法将复制流的缓冲工作转移到从节点,从而减轻主节点的负载。我们通过为 RDB文件传输打开另一个连接来实现这一点。从节点的主通道将接收复制流,而 RDB 通道则负责接收 RDB 文件

这一特性还有助于降低主节点主进程的 CPU 负载。通过为 RDB文件传输打开专用连接,`bgsave` 进程可以访问新连接,并直接将 RDB 文件流式传输到从节点。在此更改之前,由于 TLS 连接的限制,`bgsave` 进程需要将 RDB 数据写入管道,然后由主进程转发给从节点。现在这一步骤已不再必要,主进程可以避免这些昂贵的套接字读写系统调用。这也意味着 RDB 文件传输到从节点的速度会更快,因为它省略了这一步骤。

总之,复制过程将更快,主节点在全量同步期间的性能将得到提升。

实现步骤

当从节点连接到主节点时,它会发送 `rdb-channel-repl`,以告知主节点从节点支持 RDB 通道。

当从节点缺少足够的数据进行 PSYNC 时,主节点会发送 `+RDBCHANNELSYNC` 响应,并附带从节点的客户端 ID。接下来,从节点会打开一个新的连接(RDB 通道),并使用适当的能力和要求配置该连接,以与主节点建立连接。它还会通过 RDB 通道将给定的客户端 ID 发送回主节点,以便主节点将这些通道关联起来。(初始的从节点连接将被称为 `main-channel`)。然后,从节点使用 RDB 通道请求全量同步。

在 fork 操作之前,主节点会将从节点的主通道附加到复制回放日志,以便从快照结束偏移量开始传递复制流。

主节点的主进程通过主通道发送复制流,而 `bgsave` 进程则通过 RDB 通道直接将 RDB 文件发送给从节点。从节点在本地缓冲区中累积复制流,同时将 RDB 文件加载到内存中。

一旦从节点完成 RDB 文件的加载,它会关闭 RDB 通道,并将累积的复制流加载到数据库中。同步完成。

一些细节

目前,只有在主节点启用了 `repl-diskless-sync` 时,才支持 RDB 通道复制。否则,复制将通过单个连接进行,就像之前一样。

在从节点上,对复制流缓冲区有限制。从节点使用新的配置 `replica-full-sync-buffer-limit` 来限制累积的字节数。如果未设置该配置,从节点将继承 `<replica>` 的 `client-output-buffer-limit` 硬限制配置。如果我们达到这个限制,从节点将停止累积。但这并不是一个失败场景。进一步的累积将在主节点上进行。根据主节点上配置的限制,主节点可能会断开与从节点的连接。

INFO 输出中的 API 变更

1、新的副本状态:send_bulk_and_stream。表示此副本的全量同步仍在进行中。它正在并行接收复制流和 RDB 文件。

代码语言:javascript
代码运行次数:0
复制
slave0:ip=127.0.0.1,port=5002,state=send_bulk_and_stream,offset=0,lag=0

副本状态按步骤变化:

(1)首先,副本发送 `psync` 命令并接收 `+RDBCHANNELSYNC` 响应:`state=wait_bgsave`(等待 `bgsave`)

(2)当副本通过 RDB 通道建立连接并开始传输时:`state=send_bulk_and_stream`(正在发送批量数据和流数据)

(3)全量同步完成后:`state=online`(在线)

2、在副本端,复制流缓冲区的指标

(1) `replica_full_sync_buffer_size`:当前累积的复制流数据(以字节为单位)。

(2)`replica_full_sync_buffer_peak`:此实例在其生命周期内累积的最大字节数。

代码语言:javascript
代码运行次数:0
复制
replica_full_sync_buffer_size:20485             
replica_full_sync_buffer_peak:1048560

CLIENT LIST 输出中的 API 变更

在客户端列表输出中,RDB 通道客户端除了 'S' 副本标志外,还会有一个 'C' 标志:

代码语言:javascript
代码运行次数:0
复制
id=11 addr=127.0.0.1:39108 laddr=127.0.0.1:5001 fd=14 name= age=5 idle=5 flags=SC db=0 sub=0 psub=0 ssub=0 multi=-1 watch=0 qbuf=0 qbuf-free=0 argv-mem=0 multi-mem=0 rbs=1024 rbp=0 obl=0 oll=0 omem=0 tot-mem=1920 events=r cmd=psync user=default redir=-1 resp=2 lib-name= lib-ver= io-thread=0

配置变更

(1)`replica-full-sync-buffer-limit`:控制副本在 RDB 通道复制期间可以累积的复制数据量。如果未设置该配置项,则值为 0,表示副本将继承 `<replica>` 的 `client-output-buffer-limit` 硬限制配置,以限制累积的数据量。

(2)添加了 `repl-rdb-channel` 配置项,作为隐藏配置。这主要是为了测试,因为我们需要同时支持 RDB 通道复制和旧的单连接复制(以保持与旧版本的兼容性,如果未启用 `repl-diskless-sync`,则不会启用 RDB 通道复制)。该配置项会影响主节点(不响应 RDB 通道请求)和副本节点(不声明该能力)。

内部 API 变更

引入的 Redis 复制变更:

(1)在 `replconf` 命令中添加了新的复制能力:`capa rdb-channel-repl`。表示副本支持 RDB 通道复制。副本在连接到主节点时会发送该能力,与其他能力一起发送。

(2)如果副本需要全量同步,主节点会向副本的 `PSYNC` 请求回复 `+RDBCHANNELSYNC <client-id>`。

(3)当副本打开 RDB 通道连接时,作为 `replconf` 命令的一部分,它会发送 `rdb-channel 1` 以通知主节点这是 RDB 通道。同时,它还会在 `replconf` 命令中发送 `main-ch-client-id <client-id>`,以便主节点可以将这些通道关联起来。

副本状态图

具体实现细节请参考:https://github.com/redis/redis/pull/13732

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档