这是《ClickHouse 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 副本用于提高可用性、读吞吐和故障恢复能力。ClickHouse 的 ReplicatedMergeTree 依赖 Keeper 或 ZooKeeper 维护副本日志、块信息和leader 状态。
16.1 副本架构
Keeper / ZooKeeper
|
+-------------+-------------+
| | |
replica-1 replica-2 replica-3
| | |
local part local part local part
副本之间通过复制日志同步元数据,并从源副本拉取数据 part。
16.2 ReplicatedMergeTree
CREATE TABLE analytics.events_replicated
(
event_date Date,
event_time DateTime,
user_id UInt64,
event_type LowCardinality(String),
amount Decimal64(2)
)
ENGINE = ReplicatedMergeTree(
'/clickhouse/tables/{shard}/events',
'{replica}'
)
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, event_type, user_id);
路径要求:
- 同一分片内各副本路径相同;
- 不同分片路径不同;
- 不同表路径不同;
- replica 名称唯一;
- 宏配置在每台节点正确。
16.3 写入复制
客户端写 replica-1
|
v
replica-1 创建 part
|
v
写入复制日志到 Keeper
|
v
replica-2 / replica-3 感知并拉取 part
副本写入是异步同步过程。写入成功返回点、part 副本数和一致性语义要结合设置与故障场景确认,不能简单等同于同步多副本持久化。
16.4 副本引擎家族
| 本地引擎 | 副本版本 |
|---|---|
| MergeTree | ReplicatedMergeTree |
| ReplacingMergeTree | ReplicatedReplacingMergeTree |
| SummingMergeTree | ReplicatedSummingMergeTree |
| CollapsingMergeTree | ReplicatedCollapsingMergeTree |
| VersionedCollapsingMergeTree | ReplicatedVersionedCollapsingMergeTree |
先确定合并语义,再选择 Replicated 变体。
16.5 查询副本选择
Distributed 表可以配置负载均衡:
<remote_servers>
<analytics_cluster>
<shard>
<replica>
<host>ch-01</host>
<port>9000</port>
</replica>
<replica>
<host>ch-02</host>
<port>9000</port>
</replica>
</shard>
</remote_servers>
</remote_servers>
常见策略包括随机、轮询、最近主机、错误惩罚等。不同版本和配置支持有差异。生产上要确保:
- 不把查询集中到单个副本;
- 异常副本能被隔离;
- 延迟副本不提供过期结果;
- 查询超时可控制。
16.6 副本状态
SELECT
database,
table,
zookeeper_path,
replica_name,
is_readonly,
is_session_expired,
queue_size,
inserts_in_queue,
merges_in_queue,
absolute_delay
FROM system.replicas;
关键字段:
| 字段 | 含义 |
|---|---|
| is_readonly | 副本只读 |
| queue_size | 待处理复制任务 |
| absolute_delay | 副本延迟 |
| is_session_expired | Keeper 会话异常 |
| log_pointer | 复制日志位置 |
16.7 副本队列
查看任务:
SELECT
database,
table,
replica_name,
type,
source_replica,
create_time,
num_tries,
last_exception
FROM system.replication_queue
ORDER BY create_time;
常见任务类型:
| 类型 | 说明 |
|---|---|
| GET_PART | 拉取缺失 part |
| MERGE | 执行合并 |
| MUTATE | 变更数据 |
| DROP_RANGE | 删除范围 |
| ALTER_METADATA | 元数据变更 |
16.8 Keeper 与 ZooKeeper
Keeper 是 ClickHouse 内置的高可用协调服务,兼容常用 ZooKeeper 协议场景。生产建议:
- 至少 3 节点;
- 独立部署或独立资源;
- 使用低延迟 SSD;
- 监控会话和延迟;
- 避免与其他高 IO 服务争抢磁盘。
确认连接:
SELECT * FROM system.zookeeper
WHERE path = '/clickhouse';
16.9 故障场景
副本只读
可能原因:
- Keeper 不可达;
- 会话过期;
- 元数据冲突;
- 副本正在恢复;
- 管理操作设置。
排查:
SELECT database, table, is_readonly, last_queue_update, last_queue_exception
FROM system.replicas
WHERE is_readonly = 1;
队列积压
处理顺序:
- 检查网络和磁盘;
- 检查源副本是否可用;
- 查看任务异常;
- 暂停高压写入;
- 修复后等待同步;
- 必要时从健康副本重建。
Part 损坏
优先从健康副本拉取。单副本表需要备份恢复。不要在未确认路径和备份的情况下手工删除数据目录。
16.10 高可用实践
- 事实表至少两个副本;
- Keeper 三节点以上;
- 副本跨故障域部署;
- 监控 readonly、queue、delay;
- 为写入和查询设置超时;
- 定期演练副本重建;
- 保留可恢复备份;
- 升级时逐节点滚动操作。
本章小结
副本解决可用性和读扩展问题,核心依赖 ReplicatedMergeTree 与协调服务。生产上要同时关注数据同步、队列积压、副本延迟和故障域规划。副本不是分片,也不能替代备份。
思考题
- ReplicatedMergeTree 依赖什么组件?
- 副本路径和 replica 名称为什么必须正确?
- 如何判断副本延迟和队列积压?
- 副本和分片的区别是什么?
- 哪些故障需要备份而不是副本恢复?