双副本集群高可用
概述
KaiwuDB 双副本高可用方案通过引入仲裁副本概念,支持在集群中以 2 个数据副本 + 1 个仲裁副本的组合替代标准三副本部署。仲裁节点不存储时序业务数据,仅参与 Raft 共识投票,因此可部署在配置较低或与数据节点存在硬件差异的机器上,在保持自动故障转移能力的同时,降低时序数据存储开销。
说明
- 双副本策略仅对时序数据生效,关系数据和元数据仍采用三副本。
- RPO 可通过集群参数
ts.arbiter.rpo_max_duration配置,默认不限制。
基础概念
| 概念 | 描述 |
|---|---|
| 数据副本(Data Replica) | 存储实际时序业务数据的副本,正常参与 Raft 共识和选举,可当选 Leader 和 Leaseholder。双副本方案中每个数据分片有 2 个数据副本,分布在数据节点上。 |
| 仲裁副本(Arbitration Replica) | 不存储时序业务数据的副本,参与 Raft 共识和选举,可当选 Leader 但优先级较低,不可成为 Leaseholder。正常情况下 Leader 由数据副本担任,仅在数据节点故障时仲裁副本才可能当选 Leader。 |
| 仲裁节点(Arbiter Node) | 承载仲裁副本的节点,通常为集群中配置较低或异构的机器。仲裁节点仍需存储关系数据和元数据,并参与集群心跳。 |
| 数据节点(Data Node) | 承载数据副本的节点,负责时序数据的实际存储与读写服务。 |
使用限制
使用双副本高可用方案前,请注意以下限制:
- 双副本策略要求集群中至少有 2 个数据节点和 1 个仲裁节点。
- 每个数据分片的副本构成固定为 2 个数据副本 + 1 个仲裁副本,不允许通过
CONFIGURE ZONE USING num_replicas修改副本数量。 - 双副本策略只能通过
ALTER RANGE ts CONFIGURE ZONE USING arbiter = true或ALTER DATABASE ... CONFIGURE ZONE USING arbiter = true启用,不支持表级别设置,不支持对已有表从三副本切换为双副本。 - 启用双副本后,不支持切换回三副本模式。
部署配置
前提条件
- 已准备至少三台服务器,其中至少两台用作数据节点,至少一台用作仲裁节点。
- 各服务器之间网络互通,且时钟偏差小于 500 ms。
步骤
在数据节点服务器上分别执行以下命令,启动数据节点:
# 数据节点 A ./kwbase start \ --insecure \ --store=/data1 \ --listen-addr=<node_a_address>:26257 \ --advertise-addr=<node_a_address>:26257 \ --brpc-addr=:27257 \ --http-addr=<node_a_address>:8080 \ --join=<node_a_address>,<node_b_address>,<node_c_address> \ --background # 数据节点 B ./kwbase start \ --insecure \ --store=/data2 \ --listen-addr=<node_b_address>:26257 \ --advertise-addr=<node_b_address>:26257 \ --brpc-addr=:27257 \ --http-addr=<node_b_address>:8080 \ --join=<node_a_address>,<node_b_address>,<node_c_address> \ --background在仲裁节点服务器上执行以下命令,启动仲裁节点。注意必须加上
--arbiter参数:# 仲裁节点 C ./kwbase start \ --insecure \ --store=/data3 \ --arbiter \ --listen-addr=<node_c_address>:26257 \ --advertise-addr=<node_c_address>:26257 \ --brpc-addr=:27257 \ --http-addr=<node_c_address>:8080 \ --join=<node_a_address>,<node_b_address>,<node_c_address> \ --background在任意节点上执行集群初始化命令:
./kwbase init --insecure --host=<node_a_address>:26257连接到集群后,执行以下语句启用双副本策略:
-- 对全部时序数据生效,执行时集群中不能存在任何时序表 ALTER RANGE ts CONFIGURE ZONE USING arbiter = true; -- 仅对指定数据库生效,执行时目标数据库中不能存在时序表 ALTER DATABASE <db_name> CONFIGURE ZONE USING arbiter = true;系统随后会将时序数据分片自动分配为 2 个数据副本(分布在数据节点)+ 1 个仲裁副本(分布在仲裁节点),并将 Leaseholder 迁移至数据节点。
说明
- 初始化完成后副本补足和 Leaseholder 迁移需要一定时间,期间首次建表的响应时间会略长于标准三副本集群。
- 集群中没有仲裁节点时,启用双副本策略将失败。
- 启用后不支持切换回三副本模式。
扩缩容
双副本集群支持通过扩缩容处理节点故障或调整集群规模。每个数据分片的副本构成标准始终为 2 个数据副本 + 1 个仲裁副本,允许暂时缺少一个数据副本或仲裁副本,但不允许数据副本数量超过 2 个,也不允许仲裁副本数量超过 1 个。
加入新节点
当节点故障无法恢复,或需要主动扩容时,可加入新节点:
# 加入新数据节点
./kwbase start \
--insecure \
--store=/data_new \
--listen-addr=<new_node_address>:26257 \
--advertise-addr=<new_node_address>:26257 \
--brpc-addr=:27257 \
--http-addr=<new_node_address>:8080 \
--join=<existing_node_address>:26257 \
--background
# 加入新仲裁节点
./kwbase start \
--insecure \
--store=/data_new \
--arbiter \
--listen-addr=<new_node_address>:26257 \
--advertise-addr=<new_node_address>:26257 \
--brpc-addr=:27257 \
--http-addr=<new_node_address>:8080 \
--join=<existing_node_address>:26257 \
--background
新节点加入后,系统可能触发副本自动均衡,将部分副本迁移至新节点。
退役故障节点
加入新节点后,可执行退役操作移除故障节点:
./kwbase node decommission <node_id> --insecure --host=<address>:26257
退役操作会将故障节点上的副本迁移至新节点,等待命令执行完成后,所有副本已在新节点上补全。
注意
- 退役数据节点时,集群中必须至少有 3 个数据节点(即除目标节点外至少还有 2 个数据节点),否则退役将失败。
- 退役仲裁节点时,集群中必须至少有 2 个仲裁节点,否则退役将失败。
- 如果没有加入同类型的新节点以替代故障节点,缩容操作将失败。
也可以不立即执行退役,等待故障节点被系统判定为死亡后,系统会自动在其他节点上补足副本。
高可用机制
双副本方案通过 Raft 投票机制实现高可用,可容忍任意一个节点故障。
单节点故障
数据节点故障
当一个数据节点不可用时,剩余的 1 个数据副本与仲裁副本组成 2/3 多数,达成 Raft 共识,由剩余数据节点继续对外提供读写服务。节点恢复后,自动重新加入集群并与 Leader 完成数据同步,读写服务不受影响。
仲裁节点故障
当仲裁节点不可用时,2 个数据副本自身即可达成 2/2 多数,集群读写服务不受影响。节点恢复后,自动重新加入集群,恢复投票能力。
多节点故障
当任意两个节点同时故障时(包括两个数据节点同时故障,或一个数据节点与仲裁节点同时故障),集群无法达成多数共识,写入操作将失败。待任意一个节点恢复后,集群恢复服务,读写恢复正常。
当所有节点故障时,写入操作将失败。待节点全部恢复后,集群自动完成选举并恢复读写服务。
数据一致性保证
双副本方案采用弱一致性保证:数据写入 Leader 副本后即视为成功,Follower 数据副本可能存在短暂落后。可通过集群参数 ts.arbiter.rpo_max_duration 配置数据同步周期,控制最大数据丢失量。详细信息参见配置 RPO。
相关操作
配置 RPO
ts.arbiter.rpo_max_duration 用于控制双副本模式下数据节点间数据同步的时间周期,即最大允许丢失的数据时间范围。仅在启用双副本模式时生效。
SET CLUSTER SETTING ts.arbiter.rpo_max_duration = '60s';
| 取值 | 说明 |
|---|---|
-1(默认值) | 不进行 RPO 控制,数据节点之间无需进行周期性数据同步。 |
大于 1s 的时间值 | 系统按设定周期在数据节点之间同步数据,强制同步期间阻塞写入。如果有数据节点不可用,写入将被阻塞,直至数据节点恢复或新数据节点加入且故障节点退役后,写入才会继续执行。 |
注意
开启 RPO 控制后,如果有数据节点故障,写入将持续阻塞。仲裁节点故障不影响数据写入。
查看节点状态
执行以下命令查看集群节点状态,输出中 node_mode 列显示各节点角色:
./kwbase node status --insecure --host=<address>:26257
输出示例:
id | address | sql_address | build | started_at | updated_at | locality | is_available | is_live | node_mode
-----+-------------------+-------------------+---------+-----------------------------+-----------------------------+---------------+--------------+---------+-----------
1 | node_a:26257 | node_a:26257 | V3.2.0 | 2026-03-02 09:24:56.827856 | 2026-03-02 09:25:01.343206 | region=NODE1 | true | true | normal
2 | node_b:26257 | node_b:26257 | V3.2.0 | 2026-03-02 09:24:58.012345 | 2026-03-02 09:25:02.234567 | region=NODE2 | true | true | normal
3 | node_c:26257 | node_c:26257 | V3.2.0 | 2026-03-02 09:25:00.543210 | 2026-03-02 09:25:03.654321 | region=NODE3 | true | true | arbiter
node_mode 字段取值说明:
| 取值 | 说明 |
|---|---|
normal | 标准数据节点,存储时序业务数据。 |
arbiter | 仲裁节点,参与 Raft 投票,不存储时序业务数据。 |
查看监控指标
在数据监控平台的 debug/chart 页面可查看以下双副本相关监控指标:
| 指标 | 说明 | 单位 |
|---|---|---|
raft.arbiter.leader.duration | 仲裁副本作为 Leader 的时长。记录每个仲裁副本从当选 Leader 开始到变回 Follower 的时间。正常情况下该值应接近 0,数值持续偏高说明数据节点可能存在故障。 | DURATION |
arbiter.rpo.sync.paused | 开启 RPO 控制后,每次执行数据同步的副本数量。 | COUNT |