
【KaiwuDB 运维篇】多副本集群,意味着副本越多越好么?
摘要:上一篇文章我们梳理了从单机到多副本的演进路径【KaiwuDB 运维篇】高可用:从单点到多副本的进化 ,也分别介绍了 KaiwuDB 四种高可用方案。有读者问:多副本集群方案里是以5节点为例介绍的,那是不是可以理解为副本越多越好?五副本是不是比三副本更安全?这个问题值得展开聊聊。
一、副本,越多越好?
要回答这个问题,首先我们先来了解清楚副本背后的逻辑。多副本能抗故障,靠的是 Raft 共识协议。Raft 的核心逻辑不复杂:数据写入的时候,需要集群里超过半数的节点都确认这笔写入,才算真正写进去了。选主节点的时候也一样,谁拿到半数以上的选票谁当 Leader。这个"半数以上"就叫 quorum,多数派的意思。三副本的 quorum 是两票,所以最多能经得起一个节点挂掉——剩下两个还能继续干活。五副本的 quorum 是三票,能扛两个节点同时离线。副本越多容错上限越高,这个逻辑本身没错。
但多存一份数据不是免费的。每多一个副本,Leader 就要多给一个节点发日志、等它确认。副本多了,写入的延迟会变长。存储成本也跟着翻倍,三副本三倍空间,五副本就五倍。而且节点越多,网络环境越复杂,出问题的概率也大了。所以多副本不是在"多存几份"这个维度上线性变好的。三副本在多数场景下刚好是那个平衡点——扛得住单节点故障,覆盖了绝大多数业务场景的需求,同时存储开销和写入性能都在可接受范围内。五副本基本只在金融核心系统这种对容错极度敏感的场景才会用到。

还有一个更接地气的问题:实际生产环境里,服务器很少是同一年统一采购的。公司一路发展一路添机器,机房里新旧设备混着跑才是常态。三台机器里有一台配置明显偏低的情况太常见了。真遇到这种场景,标准三副本落到硬件上会有个尴尬——让这台慢机器跑完整数据副本,它可能拖累整个集群的吞吐;闲置不用,资源又浪费了。
二、KaiwuDB 多副本集群的实现
先来看数据在 KaiwuDB 的多副本集群里到底是怎么组织的。
-
数据分片(Range)是最小的数据管理单元。所有用户数据存在一个有序的键值空间里,这个空间被切成一段一段的 Range,均匀分布到各个节点上。这样做的好处是数据不会堆在一台机器上,压力自然分散了。
-
副本是每个 Range 在不同节点上的拷贝。默认每个 Range 三个副本,分布在三个不同的节点上。同一份数据由三台机器各保存一份,任何一台坏了,数据还在。
-
主副本(Leaseholder)是一个 Range 的读写入口。三个副本里只有一个 Leaseholder,由 Raft 选举产生。读写请求都走它,它挂了 Raft 自动从剩余副本里选一个新的出来。
-
节点的健康状态分三种:存活节点就是正常运行中;节点离线超过 1 分钟被标记为异常;超过默认 30 分钟标记为不可用——这时候系统会启动副本补足,在其他节点上重建缺失的副本,把 Range 拉回三副本的健康状态。

查节点状态可以用 kwbase node status 命令,输出里有 is_available 和 is_live 两个字段。两个都是 true,节点就没问题。也可以用 KaiwuDB 的监控平台直接看,更直观。拿一个五节点三副本的集群为例,介绍下当故障来了,KaiwuDB 如何让系统扛得住?
正常状态下,Range 和它的主副本在五个节点间均匀分布,没有谁特别忙、谁特别闲。当一个节点突然离线了,如果它上面有某个 Range 的主副本,Raft 会自动从其他节点重新选一个主副本出来,不需要人登录服务器去操作。选举期间正常的 DDL 和 DML 照常执行,只有正在访问故障节点的查询会挂,应用重试一次就行。
离线满 1 分钟变成异常节点,满 30 分钟后变成不可用节点。这时候因为剩下的节点(4 个)比副本数(3 个)多,系统会自动补齐缺失的副本。这个补副本的过程对上层应用是透明的,查询和写入都不受影响。如果之前用 CONFIGURE ZONE 设过副本约束,而且规则里包含了出故障的节点,副本补足可能不会自动触发,需要把故障节点从规则里摘掉。故障节点修好之后加回集群,系统自动把离线期间的数据同步回来。节点恢复期间,数据查询、DDL 和 DML 操作均不受影响。
几个实用的配置参数
不可用节点判定时间
默认情况下,如果一个节点的离线时间超过 30 分钟,系统会将其标记为不可用节点,并将该节点上的数据副本重新分配到其他节点,以确保数据的可用性和一致性。用户也可以通过以下 SQL 命令设置节点判定时间:
SET CLUSTER SETTING server.time_until_store_dead = <value>;
设置时间建议不小于 75s。注意:延长节点判定时间,可以减少节点故障对集群性能的长时间影响,但可能会影响集群的高可用性功能和 DDL 相关操作。
控制节点死亡后是否自动迁移补齐副本
系统将离线节点标记为不可用节点后,如果剩余节点数量仍大于副本数,系统将自动补足缺失的副本,确保数据的高可用性。用户也可以通过以下 SQL 命令关闭自动补足副本功能:
SET CLUSTER SETTING kv.allocator.ts_store_dead_rebalance.enabled = false;
注意:在 5 节点三副本集群中禁用该功能后,将无法承受连续节点故障。
查看节点状态
-
使用 KaiwuDB 监控平台
-
通过总览面板查看节点状态,可直观了解集群整体健康状况。

- 通过
kw-status.sh脚本(tip:该命令只适用于安装程序部署。)
kw-status
- 通过
kwbase node status命令(tip:is_available和is_live均为true表示节点正常运行,均为false表示节点异常。)
<kwbase_path>/kwbase node status [--host=<ip:port>] [--insecure | --certs-dir=<path>]
查看副本补足状态
- 使用 KaiwuDB 监控平台,通过总览面板查看副本状态,监控副本分布和健康状况。

- 通过 SQL 命令,查询是否存在副本不足或不可用分片
SELECT sum((metrics->>'ranges.unavailable')::DECIMAL)::INT AS ranges_unavailable,sum((metrics->>'ranges.underreplicated')::DECIMAL)::INT As ranges_underreplicated
FROM kwdb_internal.kv_store_status;
查看副本同步状态
- 使用 KaiwuDB 监控平台,通过分布式面板查看副本同步情况。

- Promethus 开源方案,通过导入分布式面板open in new window查看副本同步情况。
其他更多详细内容可前往 >>https://www.kaiwudb.com/docs/#/db-operation/ha/cluster-ha.html
三、多副本之外的另一个选择
标准三副本在多数场景下表现还是不错的,但有两个槽点经常被用户提出来。一个是硬件异构的老问题。公司里机器一代一代添进来,新旧混着用,总有几台配置差一些。让低配机器跑完整数据副本,磁盘和 CPU 都吃力;直接不用,又凑不齐指定数量的节点。另一个是存储成本。时序数据的量级通常比关系数据大得多,三副本意味着三倍的磁盘开销。对 IoT、工业互联网这些每天产生海量时序数据的场景来说,磁盘成本确实是一笔不小的账。
针对这两个问题,KaiwuDB 在标准多副本方案之外提供了一个更轻量的版本——双副本加仲裁副本。时序数据只存两份完整副本,第三台机器作为仲裁节点,只参与 Raft 投票、不存实际数据。这样就意味着帮助用户省了一笔钱,存储开销从三倍降到两倍左右。而且自动故障转移能力还在,仲裁节点虽然不存数据但投票权保留着,Raft 选举照常进行。节点配置要求也比三副本低,低配机器不用硬撑着跑完整副本。整体方案更轻量,对资源受限的边缘场景友好很多。

但有得也有失,因为数据副本少了,所以写入的负载均衡能力比三副本稍弱一些,极端场景下丢数据的风险也比三副本略高。但它不是用来替代三副本的——只是在特定条件和需求下多一个可选方案,对硬件预算有限、或者机器配置参差不齐的场景来说,双副本方案是一个确实能解决问题的路线。
下一篇文章,我们就专门说这个方案。感兴趣的话可以先想一下自己手头的机器情况,到时候对比着看会更有感觉。最后记得关注我们哦,后续会陆续分享更多实用干货。
附:相关术语
| 术语名称 | 中文解释 |
|---|---|
| Raft | 一种分布式共识协议,通过领导者选举和日志复制保证多节点数据一致性 |
| quorum | 多数派,Raft 协议中需要超过半数节点确认才能完成写入或选举 |
| Range | KaiwuDB 中最小的数据管理单元,将键值空间切分为多个分段进行管理 |
| Leaseholder | 主副本,每个 Range 的唯一读写入口,由 Raft 选举产生 |
| 副本 | 同一份数据在不同节点上的拷贝,用于保证数据冗余和高可用 |
| 仲裁副本 | 只参与 Raft 投票、不存储实际数据的轻量副本节点 |
| 副本补足 | 当节点不可用时,系统自动在其他节点重建缺失副本的过程 |
| CDC | Change Data Capture,变更数据捕获,实时捕获数据库中的数据变更 |
