多副本集群高可用性
概述
KaiwuDB 多副本集群具备高可用能力,能够实现故障转移和数据强一致性。集群中的各节点通过定期的心跳机制维护连接和状态,以便及时发现故障并采取相应措施。
KaiwuDB 多副本集群默认采用 3 副本机制,通过 RAFT 协议保证数据一致性和可用性,因此至少需要 2 个副本保持可用状态。
基础概念
概念 | 描述 |
---|---|
数据分片(Range) | KaiwuDB 将所有用户数据(表、索引等)和几乎所有系统数据存储在键值对的排序映射中。这个键空间被划分为多个数据分片,每个键始终可以在单个数据分片内找到。数据分片是集群高可用性和数据迁移的最小单元。 |
副本(Replica) | 每个用户数据分片默认有 3 个副本,以保证高可用性。数据迁移时,以分片副本为单位进行迁移。 |
主副本(Leaseholder) | 每个分片的主副本,负责处理该分片的读写请求。主副本通过 RAFT 协议选举产生,确保数据一致性。 |
节点状态 | KaiwuDB 中的集群节点存在以下状态: - 存活节点:默认节点状态,表示节点正常运行 - 异常节点:1 分钟内无网络连接的节点会被标记为异常节点 - 不可用节点:默认 30 分钟内无网络连接的节点将被标记为不可用节点,触发数据副本补足机制 提示: 用户可通过 KaiwuDB 监控平台和 kwbase node status 命令查看集群内的节点状态 |
机制说明
以下以 5 节点集群为例,说明 KaiwuDB 多副本集群如何实现高可用性。
正常运行
KaiwuDB 集群启动后,分片副本均匀分布在所有节点上,确保数据的高可用性和负载均衡。

单节点故障
单个节点离线后,如果该节点存在某分片的主副本,系统会自动从该分片在其他节点上的副本中重新选出新的主副本,以确保数据服务的连续性及数据一致性。
在主副本重新选举期间,集群可以正常提供服务,DDL 和 DML 操作均可正常执行。对于查询操作,只有当正在执行的查询语句涉及故障节点时,该语句才会执行失败。此时应用可以立即重新发起查询,系统能够正常响应并提供服务。

节点离线超过 1 分钟后,系统会将其标记为异常节点。节点离线时间达到设定值(默认为 30 分钟)后,系统会将该节点标记为不可用节点。如果剩余节点数量仍大于副本数,如图示中剩余 4 节点,但集群副本数为 3,此时系统自动补足缺失的副本,确保数据的高可用性。副本补足期间,数据查询、DDL 和 DML 操作均不受影响。

异常节点或不可用节点恢复后,系统会自动进行数据同步或数据补齐。节点恢复期间,数据查询、DDL 和 DML 操作均不受影响。
多节点故障
依次故障
如果两个节点依次发生故障,当第二个节点发生故障前系统已完成副本补足,则第二个节点发生故障后,系统仍支持正常运行。

同时故障
如果两个或更多节点同时出现故障,由于剩余节点数小于或等于副本数,系统无法补足缺失的副本,可能导致部分数据无法访问,甚至出现集群无法使用的情况。

说明
- KaiwuDB 1.x 和 2.0.x 版本使用导入导出方式升级到 2.0.4 版本后,多副本集群的高可用性可能会受到影响。
- 集群节点多次发生故障后重新加入,可能会导致数据写入缓慢。
- 可通过重试机制解决因
update tag
失败导致不同节点查询普通标签时的不一致问题。
相关操作
配置不可用节点判定时间
默认情况下,如果一个节点的离线时间超过 30 分钟,系统会将其标记为不可用节点,并将该节点上的数据副本重新分配到其他节点,以确保数据的可用性和一致性。
用户也可以通过以下 SQL 命令设置节点判定时间:
SET CLUSTER SETTING server.time_until_store_dead = <value>;
设置时间建议不小于 75s。注意:延长节点判定时间,可以减少节点故障对集群性能的长时间影响,但可能会影响集群的高可用性功能和 DDL 相关操作。
查看节点状态
使用 KaiwuDB 监控平台
通过总览面板查看节点状态,可直观了解集群整体健康状况。
通过
kwbase node status
命令提示
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;