ClickHouse 备份

本文说明如何使用 clickhouse_ansible 中的备份相关 Playbook,为 ClickHouse 集群建立标准化备份流程。

文中命令默认基于绿色版 Ansible 已执行 setup_portable_ansible.shsource ~/.bashrc,因此直接使用 ansible-playbook

1. 适用范围

备份相关入口包括:

  • playbooks/prepare_backup_disk.yml:配置备份磁盘。
  • playbooks/backup_cluster.yml:执行全量或增量备份。

默认文档示例以 NFS 作为备份存储。

2. 前置条件

  1. 已完成 ClickHouse 集群部署。
  2. 已在 192.168.199.162 或其他专用主机上完成 NFS 服务端配置。
  3. 备份节点能够访问备份挂载目录,例如 /backup
  4. 使用专用备份 inventory,例如 inventory/hosts.backup.ini
  5. 如果后续要做异地恢复,建议同时对恢复目标先执行一遍 NFS 挂载与备份盘准备。
  6. 备份范围内对象优先使用复制表引擎,避免单副本备份带来数据缺口。

3. 备份 inventory 最小示例

[clickhouse_backup]
ck-131-1 ansible_host=192.0.2.131 shard=1 replica=1 clickhouse_tcp_port=9000
ck-131-2 ansible_host=192.0.2.131 shard=3 replica=2 clickhouse_tcp_port=9001
ck-132-1 ansible_host=192.0.2.132 shard=1 replica=2 clickhouse_tcp_port=9000
ck-132-2 ansible_host=192.0.2.132 shard=2 replica=1 clickhouse_tcp_port=9001
ck-133-1 ansible_host=192.0.2.133 shard=2 replica=2 clickhouse_tcp_port=9000
ck-133-2 ansible_host=192.0.2.133 shard=3 replica=1 clickhouse_tcp_port=9001

[all:vars]
dbbot_inventory_purpose=backup
ansible_python_interpreter=auto_silent
ansible_user=root
ansible_ssh_pass="'<your_ssh_password>'"

说明:备份场景下建议显式填写 clickhouse_tcp_port,避免依赖端口推导逻辑。

4. 关键参数

编辑 playbooks/vars/backup_config.yml,优先确认以下参数:

  • backup_databases / backup_tables
  • backup_mode
  • backup_base_batch_id
  • backup_storage_disk
  • backup_mount_dir
  • backup_checkpoint_mode
  • backup_require_replicated_tables
  • backup_allow_partial_cluster

补充说明:

  • backup_cluster.yml 现在同样会校验 clickhouse_default_password
  • 如果你仍在用公开默认值 Dbbot_default@8888,默认会被 pre_tasks 拦截;实验环境才建议显式设置 fcs_allow_dbbot_default_passwd: true

5. 首次配置 NFS 与备份磁盘

5.1 配置 NFS 服务端

cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
  -i ../inventory/hosts.nfs_server.ini \
  setup_nfs_server.yml

默认会在 192.168.199.162 上导出 /srv/nfs/clickhouse_backup

5.2 在源集群挂载 NFS

cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
  -i ../inventory/hosts.backup.ini \
  setup_nfs_client_mount_rc_local.yml

5.3 为备份节点写入 ClickHouse 备份盘配置

cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
  -i ../inventory/hosts.backup.ini \
  prepare_backup_disk.yml \
  -e "backup_storage_disk=backup_nfs backup_mount_dir=/backup"

执行后应确认 system.disks 中可见对应备份磁盘。

5.4 如果后续要恢复到容灾集群,提前准备 DR 侧备份盘

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.backup.ini \
  backup_cluster.yml \
  -e '{"backup_databases":["biz_db"],"backup_mode":"full"}'

如果你希望固定批次号,可显式传入 backup_batch_id

cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
  -i ../inventory/hosts.backup.ini \
  backup_cluster.yml \
  -e '{"backup_databases":["biz_db"],"backup_mode":"full","backup_batch_id":"20260306T210000_CST_bk001"}'

7. 执行增量备份

cd /usr/local/dbbot/clickhouse_ansible/playbooks
ansible-playbook \
  -i ../inventory/hosts.backup.ini \
  backup_cluster.yml \
  -e '{"backup_databases":["biz_db"],"backup_mode":"incremental","backup_base_batch_id":"20260306T210000_CST_bk001"}'

8. 备份产物与口径

成功执行后,备份流程通常会输出以下信息:

  • backup_batch_id
  • safe_ts
  • manifest 路径

manifest 默认会写入两份:

  • 备份目录:/backup/<cluster>/<batch_id>/manifest/manifest.json
  • 控制节点:artifacts/manifests/backup/<batch_id>.json

其中 safe_ts 可作为后续业务补数或数据回放的时间口径。

9. 备份前后的验证

9.1 复制健康检查

SELECT database, table, is_readonly, queue_size, absolute_delay
FROM system.replicas
ORDER BY database, table;

9.2 检查备份结果

jq '{batch_id, cluster_name, backup_mode, safe_ts, results}' \
  /backup/<cluster>/<batch_id>/manifest/manifest.json

10. 风险与建议

  1. 默认策略每个分片只选一个副本做物理备份,用于减少重复 IO。
  2. 如果备份范围内存在非复制本地表,建议先整改后再执行生产备份。
  3. 不建议对备份 Playbook 使用 --check 模式。
  4. 生产环境建议保留固定命名规范的批次号,便于审计和恢复。
  5. 对恢复目标的 NFS 挂载和 prepare_backup_disk.yml 不应等到真正灾难发生时才第一次执行,建议在演练阶段就固化。