K-Safety 最佳实践¶
编译:JiangChong
原文:K-Safety Best Practices | 作者:Shrirang Kamat、Soniya Shah
📝 文章说明:本文基于 Vertica 官方 KB 原文翻译整理。原文仅讨论了 Enterprise 模式下的 K-safety 机制(buddy projection、节点依赖环),未涉及 Eon 模式。译者根据 Vertica 26.2.x 官方架构文档 和 vault 已有知识,补充了 Eon 模式分片订阅机制、Quorum + 分片覆盖双条件模型、Elastic K-safety 自动保护、双主子集群容错、Fault Group 实操配置(含自动/手动两种类型)、节点恢复流程、以及 Enterprise/Eon K-Safety 方案对比。新增内容位于「Eon 模式下的 K-Safety 与高可用」章节。
概述¶
本文档涵盖 K-safety、数据安全性及节点依赖关系的核心概念,是理解 Vertica 高可用与恢复机制的基础。原文仅覆盖 Enterprise 模式;本文补充了 Eon 模式(计算-存储分离)下的高可用机制,包括分片订阅(Shard Subscription)、双主子集群容错、以及两种模式的方案对比与选型决策框架。
K-Safety¶
K-safety 衡量数据库集群的容错能力。K 值表示数据库中数据副本的数量。要在 Vertica 中实现高可用,分段投影必须至少有 1 个 buddy projection,非分段投影则必须在所有节点上复制。Vertica 通过 K-safety 来强制执行这些投影要求。
K=1 的约束¶
在 K-safety = 1 的数据库中,Vertica 自动创建的投影会带有 buddy projection。但如果手动创建投影时未指定 ksafe1 关键字,该投影就不会有 buddy projection,并将被标记为 unsafe(不安全),受到以下限制:
- 不会更新(not up to date)
- 无法刷新
- 无法接收加载的数据
- 不能用于查询
检查 K-Safety¶
监控系统级 K-safety 状态(来源:v_monitor.SYSTEM 表):
SELECT node_count, node_down_count, current_fault_tolerance
FROM v_monitor.system;
-- node_count: 集群总节点数
-- node_down_count: 当前 DOWN 的节点数
-- current_fault_tolerance: 当前 K-safety 级别
数据安全性(Data Safety)¶
非分段投影在集群每个节点上都有一份数据副本。对于 K=1 的数据库,每个分段投影都有一个包含数据副本的 buddy projection。
分段与 Buddy 节点¶
在分段投影中,数据根据投影设计中指定的分段表达式拆分为多个 segment。属于分段投影及其 buddy projection 的数据 segment 在节点上偏移分布。
拥有某个数据 segment 及其副本的两个节点称为 buddy 节点。它们之间共享依赖关系。
下图展示了节点依赖关系。节点 1 和节点 2 是 buddy 节点,共享数据 segment S1 的依赖;节点 2 和节点 3 共享 segment S2 的依赖,以此类推:

查询节点依赖¶
方法 1 — buddy pair 列表:
SELECT dependency_id, min(node_name) AS node_x, max(node_name) AS node_y
FROM vs_node_dependencies JOIN nodes ON node_oid = node_id
GROUP BY 1 HAVING count(*) = 2 ORDER BY 1;
输出示例:
dependency_id | node_x | node_y
--------------+----------------------+----------------------
0 | node1 | node3
1 | node2 | node4
2 | node3 | node4
3 | node2 | node5
4 | node1 | node5
(5 rows)
方法 2 — 位图方式:
输出示例:
get_node_dependencies
-----------------------------------------------------------------------------
Deps:
00110 - cnt: 2
01001 - cnt: 2
01100 - cnt: 2
10001 - cnt: 2
10010 - cnt: 2
11111 - cnt: 9
00001 – name: Node 2
00010 – name: Node 1
00100 – name: Node 3
01000 – name: Node 4
10000 – name: Node 5
(1 row)
方法 3(8.0.1+)— 带节点名称的详细输出:
位图解读¶
8.0.1 之前的版本中,
get_node_dependencies不提供位到节点的映射。最右 bit 代表 node_id 最小的节点,最左 bit 代表 node_id 最大的节点。
查看节点按 node_id 升序排列的名称:
- bit 值 1 = 该节点与另一个同样 bit=1 的节点互为 buddy
- 例如位图
00110:node_id 第二小的节点和 node_id 第三小的节点是 buddy cnt= 该依赖关系对应的 projection buddy pair 数量- 全 1 的位图(如
11111) = 非分段投影,cnt表示数据库中非分段投影的数量
依赖环¶
如果将节点视为顶点、节点间的依赖关系视为边画成图,K=1 的数据库会形成一个环,每个顶点有 2 条边:

- 如果环中所有节点都有 3 条边 → K=2
- 如果仅部分节点有多于 2 条边 → rebalance 未完成
重新计算节点依赖¶
高可用与数据安全性¶
K=1 的 Vertica 数据库在满足以下条件时保持 UP 且完全可用:
- 数据库中超过半数节点处于 UP 状态
- 依赖环中没有相邻的两个节点同时 DOWN
这个特性称为 data safety。
举例¶
- 节点 1 和节点 4 同时宕机 → ✅ 数据库仍 UP(不相邻)
- 节点 1 和节点 5 同时宕机 → ❌ unsafe SHUTDOWN(相邻,数据 segment 不可访问)
查询关键节点¶
当有节点 DOWN 时,可查询关键节点列表。当数据库管理员计划对多个节点同时进行维护时,该结果表尤其有用:
最佳实践建议¶
1. 只用 K=1,不推荐 K=2¶
| K=1 | K=2 |
|---|---|
| 资源消耗基准 | 多消耗约 50% 存储空间 |
| 不容忍相邻节点同时 DOWN | 可容忍相邻两节点同时 DOWN |
| 推荐 | 不推荐(相邻双节点同时宕机概率极低,得不偿失) |
2. 大集群配置 Fault Groups(故障组)¶
对于跨越两个以上机架的集群,通过定义 fault group 实现机架感知,确保 buddy segment 分布在不同故障域,避免单机架故障导致相邻节点同时 DOWN。
Fault Group 类型(来源:26.2.x 官方文档):
| 类型 | 触发条件 | 说明 |
|---|---|---|
| 自动 | 集群 ≥120 节点 | Vertica 自动围绕控制节点(control nodes)创建 fault group |
| 手动 | 有相关故障风险 / 需影响控制消息路由 | 梳理物理拓扑 → 编写输入文件 → 运行 Vertica 脚本生成 SQL → 执行 |
⚠️ 限制:Fault Group 无法防范单点故障(如单台网络交换机故障导致全集群不可达)。
查看 Fault Group 配置(来源:FAULT_GROUPS):
SELECT * FROM fault_groups;
-- member_name: 节点名或子组名
-- member_type: 'node' 或 'faultgroup'
-- parent_name: 上级 group 名
重新计算节点依赖(配置 Fault Group 后):
注意:Fault Group 是 Enterprise 模式专属功能。Eon 模式下通过分片订阅的物理节点分布规划实现等效的故障域隔离(见「Eon 模式下的高可用配置」章节)。
数据库恢复与 Data Safety¶
启动 Vertica 时需要:
- 超过半数节点形成 quorum(法定人数)
- 依赖环中不能有相邻节点被排除在外
详见 Vertica 文档:K-Safety
Eon 模式下的 K-Safety 与高可用¶
以上内容基于 Enterprise 模式(数据存本地磁盘、通过 buddy projection 实现副本)。Vertica 自 9.x 引入 Eon 模式(计算-存储分离,数据存公共存储如 S3/HDFS/MinIO),其高可用机制与 Enterprise 模式有根本性差异。本节补充 Eon 模式下的 K-Safety 原理、故障场景与操作指南。
架构差异:Buddy Projection → Shard Subscription¶
Enterprise 模式下,每个分段投影有一个 buddy projection(物理副本),节点两两组成 buddy pair,K=1 保证任意两个相邻节点不同时宕机即可。
Eon 模式下,数据不在本地磁盘上——所有数据持久化在公共存储(communal storage),节点只持有本地缓存(Depot)。副本机制通过 分片(Shard) 实现:
| 维度 | Enterprise 模式 | Eon 模式 |
|---|---|---|
| 数据位置 | 节点本地磁盘 | 公共存储(S3/HDFS/MinIO) |
| 副本机制 | Buddy Projection(物理副本) | Shard Subscription(分片订阅) |
| 容错单元 | Buddy Pair(2 节点互为备份) | Shard Replica(同一分片被多个节点订阅) |
| 相邻节点同时宕机 | 数据库 unsafe shutdown | 分片订阅丢失 → 集群进入 READONLY |
| 节点恢复 | 恢复节点 + AHM 推进 | revive_db 复活数据库 / 节点重新订阅分片 |
| 弹性伸缩 | 需要 rebalance(小时~天级) | 无需 rebalance(分钟级,见 Vertica 弹性伸缩功能介绍与配置) |
Eon 模式的 Data Safety:分片订阅机制¶
Eon 数据库创建时,数据被哈希切分为多个 分片(Shard)。每个分片被 至少 2 个节点订阅(相当于 Enterprise 的 K=1)。节点宕机时的行为:
- 单个节点宕机:该节点订阅的分片由其他订阅节点继续提供服务,集群正常运行
- 同一分片的 2 个订阅节点同时宕机:分片数据无法访问 → 集群所有节点进入 READONLY 状态
- 集群 READONLY 后:恢复宕机节点时,其余节点会自动重启以从 READONLY 切换回 READWRITE
查询分片订阅状态(来源:NODE_SUBSCRIPTIONS):
-- 查看每个节点订阅了哪些分片及其状态
SELECT node_name, shard_name, subscription_state,
is_primary, is_participating_primary
FROM v_catalog.node_subscriptions
ORDER BY shard_name, node_name;
查询分片订阅的节点对数(判断风险):
-- 检查每个分片有几个订阅节点(少于 2 则为单点风险)
SELECT shard_name, count(*) AS subscriber_count
FROM v_catalog.node_subscriptions
WHERE subscription_state = 'ACTIVE'
GROUP BY 1
HAVING count(*) < 2;
来源:SHARDS 表列出所有分片及其哈希边界。
Eon K-safety:Quorum + 分片覆盖¶
Eon 模式数据库保持正常运行的两个条件(来源:26.2.x 官方文档):
- 维持 Quorum:超过半数(50%+1)的主子集群节点(primary nodes) 处于 UP 状态。例如 6 个 primary 节点,至少需要 4 个 UP。注意:Vertica 只统计 当前归属于数据库的 primary 节点——正常流程移除的节点不再计入 quorum 计算(注:文档未直接说明此行为,推断依据是 Vertica 的 K-safety 下限保护机制:移除前会检查是否低于当前 K-safety 要求的最小节点数)。
- 维持分片覆盖(Shard Coverage):每个分片至少有一个订阅它的 primary 节点,该节点负责为该分片执行 Tuple Mover 操作。如果任一 shard 失去所有 primary 订阅者,数据库进入 READONLY 模式。
K=1 下的分片订阅模型:
- 每个分片有 两个订阅者:一个 primary subscriber(负责 Tuple Mover)和一个 secondary subscriber(持有分片 catalog 元数据副本)
- secondary subscriber 不维护独立的 depot 缓存——接管时直接从公共存储读取,性能会下降
- 因此宕机后应尽快恢复或替换 primary 节点
Elastic K-safety(弹性 K-safety)¶
Eon 模式默认启用的自动保护机制:当分片的 primary 或 secondary 订阅者宕机时,Vertica 自动将另一个 primary 节点订阅到该分片。新节点需要获取分片元数据副本,完成后即可作为备份接管。
弹性 K-safety 的限制——以 10 个 primary 节点的 K=1 数据库为例:
UP ≥ 8 → 继续新增弹性订阅(离 quorum 丢失还有 3 个 buffer)
UP = 7 → 停止新增(再失去 1 个就只剩 6,离 quorum 丢失只差 1)
UP ≤ 5 → 丢失 quorum,集群 READONLY
通用公式:停止阈值为 N/2 + K + 1。当 UP 节点数低于等于该值时,新增订阅已无意义——再宕一个 primary 就逼近 quorum 红线(> N/2),多一个备份也救不了。
一旦宕机节点恢复并重新加入集群,Vertica 自动移除弹性 K-safety 期间添加的额外订阅,分片订阅关系恢复原状。
Eon K-safety 级别与最小节点要求¶
Eon 模式与 Enterprise 模式在 K-safety 设置上的关键区别:Eon 模式下,只要有 3 个或以上 primary 节点,Vertica 自动将 K-safety 设为 1(K=1)——不需要像 Enterprise 那样手动设计物理 schema 并调用 MARK_DESIGN_KSAFE。
| K-safety | 最小 primary 节点数 | 说明 |
|---|---|---|
| K=0 | 1 | 单节点 Eon,仅推荐用于测试。失去 primary 节点立即 READONLY |
| K=1(推荐) | 3 | 每个 shard 有 2 个订阅者,容忍 1 个 primary 节点宕机 |
| K=2 | 5 | 每个 shard 有 3 个订阅者,容忍 2 个 primary 节点宕机。云环境通常不需要 |
如需手动调整 K-safety 级别:
SELECT MARK_DESIGN_KSAFE(N)→SELECT REBALANCE_SHARDS()。
查询关键节点与关键子集群¶
当有 primary 节点宕机时,持有其分片 secondary 订阅的节点变为关键节点(失去它会导致分片覆盖丢失)。Eon 模式还提供了关键子集群的概念:
-- 查关键节点(Enterprise / Eon 通用)
SELECT * FROM critical_nodes;
-- 查关键子集群(Eon 专属,26.2.x 文档)
SELECT * FROM critical_subclusters;
维护前务必检查这两个表,确认计划停止的节点/子集群不在其中。
真实案例:Eon 相邻节点宕机 → 集群 READONLY¶
以下案例来自某 Eon 集群故障报告,展示了 Eon 模式下「逻辑相邻节点」同时宕机的典型故障链:
- 触发:某 SQL 触发产品 Bug,导致
v_db_node0001和v_db_node0002同时 PANIC - 影响:这两个节点恰好订阅了同一个分片,同时宕机后分片订阅丢失
- 结果:集群剩余节点全部进入 READONLY 状态
- 恢复:启动宕机节点后,READONLY 节点自动重启恢复为 READWRITE
关键启示:Eon 模式下,不仅要关注物理机架分布,更要关注分片订阅的节点分布——两个订阅同一分片的节点如果落在同一机架/同一虚拟机宿主上,存在单点风险。
Eon 模式下的高可用配置¶
1. 子集群(Subcluster)级别的容错¶
Eon 模式支持双主子集群(Dual Primary Subcluster) 部署,两个主子集群各自订阅完整的分片集。注意:双主子集群的作用是计划内维护(先降级再关,另一个继续服务),而非自动容错——直接关闭任意一个主子集群会导致集群 READONLY(见下方操作流程)。
⚠️ 来自 Eon双主子集群的注意事项:关闭主子集群前必须先执行
DEMOTE_SUBCLUSTER_TO_SECONDARY(),否则集群立即 READONLY。
-- 关闭主子集群的正确流程
SELECT DEMOTE_SUBCLUSTER_TO_SECONDARY('subcluster2'); -- 先降级
-- 再通过 admintools 停止子集群
-- admintools -t stop_subcluster -c subcluster2 -d <db> -Fi
-- 重启后恢复
-- admintools -t restart_subcluster -c subcluster2 -d <db> -Fi
SELECT PROMOTE_SUBCLUSTER_TO_PRIMARY('subcluster2'); -- 再升回
2. 分片订阅的物理分布(Eon 的 "Fault Domain")¶
Eon 模式没有 Fault Group 机制(Fault Group 是 Enterprise 专属概念,见 FAULT_GROUPS)。Eon 通过以下方式实现跨故障域的冗余:
a) Vertica 自动分布:创建数据库时,Vertica 自动将同一分片的 primary 和 secondary 订阅分配到不同节点。在规划节点的物理位置时,确保同一分片的订阅节点落在不同机架/交换机下即可。
b) 分片数量规划(来源:26.2.x 官方文档):Vertica 推荐分片数为 12 的倍数,且最好是子集群节点数的倍数。分片数过少会导致节点负载不均,过多则增加元数据开销。
-- 查看当前分片分布
SELECT shard_name, shard_type, is_replicated,
lower_hash_bound, upper_hash_bound
FROM v_catalog.shards
ORDER BY shard_name;
c) 节点订阅分布检查:确认同一分片的订阅节点未集中在同一物理位置:
-- 列出每个分片的所有订阅节点
SELECT shard_name, node_name, subscription_state, is_primary
FROM v_catalog.node_subscriptions
ORDER BY shard_name, is_primary DESC;
如需调整分片订阅分布,使用
SELECT REBALANCE_SHARDS();。
3. Eon 节点替换 vs. 恢复¶
Eon 模式下节点替换与 Enterprise 模式的关键区别:
| 场景 | Enterprise 模式 | Eon 模式 |
|---|---|---|
| 单节点故障 | 恢复节点,AHM 推进 | 新节点重新订阅分片,从公共存储拉数据 |
| 全部节点故障 | 需从备份恢复 | revive_db 从公共存储复活数据库 |
| 替换节点后启动 | 通常正常 | 可能卡在 Waiting for Cluster Invite(Catalog >20GB 时需设 TSCatalogInvite=0) |
revive_db 复活数据库(来源:Eon 数据库替换节点过后节点启动卡在等待邀请步骤且重启数据库失败):
# 先做 dry-run 检查
admintools -t revive_db --display-only \
--communal-storage-location=webhdfs://hacluster/verticaeon/<dbname> \
-d <dbname>
# 正式复活(需指定所有节点)
admintools -t revive_db \
--communal-storage-location=webhdfs://hacluster/verticaeon/<dbname> \
-s 'v001,v002,...' --force \
-d <dbname>
# 启动
admintools -t start_db -d <dbname> -F
常见坑(来源:Eon数据库性能问题原因):
- 节点替换/恢复时会触发
drop/remove subscription操作,产生 GCL-X 锁,可能导致短期性能下降 - 若 GCL-X 锁 30 分钟内无法获取(公共存储 NN 异常),可能导致集群宕机
- Catalog >20GB 时需设置
TSCatalogInvite=0避免启动超时
Enterprise vs Eon:K-Safety 方案对比¶
| 维度 | Enterprise K=1 | Eon 单主子集群 | Eon 双主子集群 |
|---|---|---|---|
| 容错能力 | 容忍非相邻节点宕机 | 容忍非同一 shard 节点宕机 | 同单主子集群;额外支持计划内维护不停服 |
| 相邻节点全宕 | Unsafe SHUTDOWN | 集群 READONLY | 同上;但可通过降级→关闭→升级实现零停机维护 |
| 恢复方式 | 恢复节点 + AHM | 恢复节点 / revive_db | 恢复节点 / 切换主子集群 |
| 额外资源 | 基准 | 公共存储成本 | 公共存储 + 双倍计算资源 |
| 弹性伸缩 | 需 rebalance(小时~天) | 分钟级,无需 rebalance | 分钟级,无需 rebalance |
| 适用场景 | 传统硬件部署、固定规模 | 云部署、弹性规模 | 高 SLA 要求、零停机维护 |
决策框架:选 Eon 还是 Enterprise?¶
需要弹性伸缩(分钟级加减节点)?
├── 是 → Eon 模式
│ ├── SLA 要求 >99.9%?→ 双主子集群
│ └── SLA 要求 ≤99.9%? → 单主子集群 + 跨故障域分布分片订阅
└── 否 → Enterprise 模式
├── 多机架?→ 配置 Fault Group
└── 单机架?→ K=1 即可,不推荐 K=2
更多 Eon 模式与 Enterprise 模式的对比详见 Vertica 弹性伸缩功能介绍与配置,Eon 模式分片规划详见 Vertica Eon 模式中分片、节点和 Depot 选择的最佳实践。
扩展阅读¶
- Vertica 弹性伸缩功能介绍与配置 — Enterprise vs Eon 弹性伸缩原理与操作
- Vertica Eon 模式中分片、节点和 Depot 选择的最佳实践 — Eon 分片规划
- Vertica 集群 Rebalance 完全指南 — Enterprise 模式 rebalance 细节
- Eon双主子集群的注意事项 — 双主子集群关闭/启动的正确流程
- NODE_SUBSCRIPTIONS — 分片订阅系统表参考
- SHARDS — 分片系统表参考
- FAULT_GROUPS — Fault Group 系统表参考
关键 SQL 速查¶
| 用途 | SQL | 适用模式 |
|---|---|---|
| 查 K-safety | SELECT GET_DESIGN_KSAFE(); |
Enterprise / Eon |
| 查系统级 K-safety 状态 | SELECT node_count, node_down_count, current_fault_tolerance FROM v_monitor.system; |
Enterprise / Eon |
| 查 buddy pair | SELECT ... FROM vs_node_dependencies JOIN nodes ... |
Enterprise |
| 查依赖位图 | SELECT GET_NODE_DEPENDENCIES(); |
Enterprise |
| 查依赖位图+名称(8.0.1+) | SELECT get_node_dependencies_verbose(); |
Enterprise |
| 重算节点依赖 | SELECT RECOMPUTE_NODE_DEPENDENCIES(); |
Enterprise / Eon |
| 查关键节点 | SELECT * FROM critical_nodes; |
Enterprise / Eon |
| 查关键子集群 | SELECT * FROM critical_subclusters; |
Eon |
| 查分片订阅状态 | SELECT * FROM v_catalog.node_subscriptions; |
Eon |
| 查分片信息 | SELECT * FROM v_catalog.shards; |
Eon |
| 查 Fault Group | SELECT * FROM fault_groups; |
Enterprise |
| 查 READONLY 事件 | SELECT * FROM active_events WHERE event_code = 20; |
Eon |
| 设置 Eon K-safety 级别 | SELECT MARK_DESIGN_KSAFE(N); → SELECT REBALANCE_SHARDS(); |
Eon |
| 复活 Eon 数据库 | admintools -t revive_db ... |
Eon |