ClickHouse 恢复
本文说明如何使用 clickhouse_ansible 中的恢复 Playbook,将备份批次恢复到目标 ClickHouse 集群。
文中命令默认基于绿色版 Ansible 已执行 setup_portable_ansible.sh 并 source ~/.bashrc,因此直接使用 ansible-playbook。
1. 恢复原理概览
恢复流程默认以备份 manifest 为输入,并使用“每分片主副本全量恢复,其他副本结构恢复”的策略:
- 每个分片选定一个主副本执行全量恢复。
- 其他副本执行
structure_only恢复,补齐结构与复制元数据。 - 随后由 ClickHouse 复制机制完成其余数据追平。
这样可以减少所有副本同时从备份盘做全量导入带来的重复 IO。
2. 前置条件
- 已存在可用备份批次和 manifest 文件。
- 目标集群已完成 NFS 挂载,并正确配置备份磁盘,例如
backup_nfs。 - 目标节点均能访问备份挂载目录,例如
/backup。 - 使用专用恢复 inventory,例如
inventory/hosts.restore.ini。 - 若目标是原集群灾难恢复,需要先完成停写和对象清理。
- 如果是默认演练环境,恢复目标为
192.168.199.141/142/143,备份盘准备使用inventory/hosts.dr_backup.ini,恢复执行使用inventory/hosts.restore.ini。
3. 恢复 inventory 最小示例
[clickhouse_restore]
ck-141-1 ansible_host=198.51.100.141 shard=1 replica=1 clickhouse_tcp_port=9000
ck-141-2 ansible_host=198.51.100.141 shard=3 replica=2 clickhouse_tcp_port=9001
ck-142-1 ansible_host=198.51.100.142 shard=1 replica=2 clickhouse_tcp_port=9000
ck-142-2 ansible_host=198.51.100.142 shard=2 replica=1 clickhouse_tcp_port=9001
ck-143-1 ansible_host=198.51.100.143 shard=2 replica=2 clickhouse_tcp_port=9000
ck-143-2 ansible_host=198.51.100.143 shard=3 replica=1 clickhouse_tcp_port=9001
[all:vars]
dbbot_inventory_purpose=restore
ansible_python_interpreter=auto_silent
ansible_user=root
ansible_ssh_pass="'<your_ssh_password>'"
4. 关键参数
编辑 playbooks/vars/restore_config.yml,重点确认:
restore_batch_idrestore_manifest_filerestore_to_all_replicasrestore_allow_non_empty_tablesrestore_require_manual_confirmrestore_enable_two_phase_mv_compatrestore_allow_partial_cluster
补充说明:
restore_cluster.yml也会校验clickhouse_default_password。- 如果你仍在用公开默认值
Dbbot_default@8888,默认会被pre_tasks拦截;实验环境才建议显式设置fcs_allow_dbbot_default_passwd: true。
5. 恢复前的目标集群准备
cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
-i ../inventory/hosts.dr_backup.ini \
setup_nfs_client_mount_rc_local.yml
ansible-playbook \
-i ../inventory/hosts.dr_backup.ini \
prepare_backup_disk.yml \
-e "backup_storage_disk=backup_nfs backup_mount_dir=/backup"
上面两步必须先在恢复目标集群执行完成,然后再进入正式恢复。
6. 标准恢复命令
cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
-i ../inventory/hosts.restore.ini \
restore_cluster.yml \
-e "restore_batch_id=20260306T210000_CST_bk001"
默认会提示输入确认短语,例如:RESTORE 20260306T210000_CST_bk001。
7. 单副本恢复模式
如果你只希望每个分片恢复一个副本,可临时覆盖:
cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
-i ../inventory/hosts.restore.ini \
restore_cluster.yml \
-e "restore_batch_id=20260306T210000_CST_bk001 restore_to_all_replicas=false"
该模式更适合演练或特殊场景;在生产使用时,应先确认表结构和复制策略已满足要求。
8. 原集群灾难恢复的推荐顺序
- 停止业务写入,冻结变更窗口。
- 选定恢复批次,核对 manifest 中的
safe_ts。 - 使用恢复专用 inventory 指向目标集群。
- 人工清理需要恢复的数据库或表。
- 执行
restore_cluster.yml。 - 校验行数、副本状态和复制健康。
- 以
safe_ts为起点执行业务补数或回放。
9. 恢复后验证
8.1 总量核对
SELECT count() FROM <db>.<distributed_table>;
8.2 各副本本地行数
SELECT
hostName() AS host,
tcpPort() AS port,
count() AS rows
FROM clusterAllReplicas('<cluster>', '<db>', '<local_table>')
GROUP BY host, port
ORDER BY host, port;
8.3 复制健康
SELECT table, is_readonly, queue_size, absolute_delay
FROM system.replicas
WHERE database = '<db>'
ORDER BY table;
8.4 TTL 表的验收口径
如果恢复对象带有 TTL ... DELETE,不要直接拿源集群与目标集群的全表 count() 做强一致验收。
原因:
RESTORE只负责把 part 恢复回来。TTL DELETE依赖后台 merge 异步清理,不会在恢复时瞬间全部完成。- 即使手工执行
ALTER TABLE ... MATERIALIZE TTL,源集群和目标集群的执行时刻也可能不同,TTL 边界附近的少量数据仍可能继续漂移。
例如,mysql_slowlog_raw_local 默认是:
- 造数跨度
60天 - 表 TTL
30 DAY DELETE
这种组合更适合演示 TTL 行为,不适合直接用“全表总数必须完全一样”来做恢复验收。
对 TTL 表,推荐使用以下两种方式之一:
- 使用固定时间窗口做对比,源和目标都使用同一个字面 cutoff:
SELECT count()
FROM lab_ck_biz.mysql_slowlog_raw_local
WHERE log_time >= toDateTime('2026-02-07 00:00:00');
- 优先选择无 TTL 的业务表做恢复一致性验收。
如果只是想加快 TTL 清理,可在源和目标都执行:
ALTER TABLE lab_ck_biz.mysql_slowlog_raw_local
ON CLUSTER 'example_3shards_2replicas'
MATERIALIZE TTL
SETTINGS mutations_sync = 2;
但要注意:这条命令只能帮助加快 TTL 收敛,仍不建议把 TTL 表的“全表总数完全一致”作为唯一验收标准。
10. 注意事项
- 恢复 Playbook 默认要求 inventory 文件名包含
restore且设置dbbot_inventory_purpose=restore。 - Playbook 不会自动执行高风险的
DROP DATABASE或DROP TABLE,这些动作需要人工复核后执行。 - 对包含物化视图的场景,默认启用两阶段兼容恢复逻辑。
- 若备份中包含配置快照,是否回放配置应结合变更窗口和目标环境评估后再决定。
- 恢复目标侧的 NFS 挂载和
prepare_backup_disk.yml不会由restore_cluster.yml自动代劳,必须提前准备好。 - 如果要做源集群与目标集群的跨集群验收,请使用独立的 ClickHouse 恢复后数据校验 文档与
validate_restore_consistency.yml。