一个 Clickhouse 集群磁盘损坏恢复数据的案例
通过一个故障案例,理解 ClickHouse 分布式机制。
作者:张宇,爱可生DBA,负责数据库运维和故障分析。擅长 ClickHouse、MySQL、Oracle,爱好骑行、AI、动漫和技术分享。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 1500 字,预计阅读需要 5 分钟。
业务场景
在日常运维的某个系统下,有一套 4 分片 3 副本的高可用分布式的 ClickHouse 集群。当前分片的每个节点的数据量为 5.6TB。
故障背景
监控发现其中的一个节点无法使用,后续排查发现 5 块磁盘已经损坏,Raid10 也无法保证数据完整,导致数据目录全部重新换成新的磁盘,而且使用的是传统机械盘,速度慢。现在联系厂商更换磁盘,需要停用此节点,等厂商更换完毕之后,需要配合恢复数据。
恢复思路
ClickHouse 的集群是一个分布式的集群,每个分片的数据不同,所有分片的数据加起来才是一份完整的数据,每个分片副本的数据是相同的,这就是 ClickHouse 数据的高可用。
本次也是非常典型的故障,硬件做了 Raid10,但是 Raid10 磁盘基本上全部坏掉了,导致 Raid10 离线也无法使用,最后更换了所有的磁盘,导致整个数据目录变成了空的。
因为此副本为一个分片中的其中一个副本,还有其他两个副本在线,所以业务使用无影响,而且我们可以通过其他副本里面的数据开始恢复此副本的数据。
恢复的基本原理: 同一个分片里面 Zookeeper 路径相同的表,但是副本名不同。数据是会自动验证同步的,所以我们只需要重建表,并且保证 Zookeeper 地址一致,副本名不一致,就会自动开始同步数据,直到两个副本数据完全一致。
副本之间是如何同步数据的呢?
Zookeeper 里面存放了副本数据文件 parts 的路径。如果当前副本没有这些 parts 就会通过 Zookeeper 得到其他副本的 parts 路径,然后通过 9009
端口进行数据文件的传输,然后恢复数据。
如下是官方的原理图:
查看节点是否存在残留数据
-
clickhouse-1:同一个分片正常副本
-
clickhouse-2:坏掉的副本
shell> clickhouse-client --password clickhouse-2> show databases;
经过确认无残留数据。
查看当前节点的副本
clickhouse-2>select * from system.clusters;
is_local
为 1 就是当前登录的节点。
恢复数据
因为旧节点磁盘损坏,所以需要在它的其他副本得到这些信息,然后到损坏的节点执行:
shell> clickhouse-client --password --host=xxx.xxx.77.30 --port=9000 clickhouse-1>select database,table,replica_is_active from system.replicas;
第三副本的表全部都无法访问。
导出清理 Zookeeper 元数据的 SQL 语句。
因为只是磁盘坏了,本地数据没有了,但是 Zookeeper 里面的数据还存在,如果不清理,重建表的时候会导致元数据冲突无法创建表。
创建清理 Zookeeper 元数据的 SQL 文件。
shell> vim clear_zk.sql
清理 Zookeeper 的元数据。
shell> clickhouse-client --password --port 9000 --multiquery < clear_zk.sql 2&>1 clear.log7
导出表结构。
clickhouse-1>select zookeeper_path ,create_table_query from system.tables a right join system.replicas b on a.name=b.table where a.database in ('xxx','xxx','xxx') ;
创建所有数据库。
clickhouse-2>create database xxx;
创建建表的 SQL 文件。
PS:要注意这个标红的一定要和 Zookeeper 元数据的地址一样,就是上面导出来的时候第一列就是 Zookeeper 的元数据的地址,一定要好好验证,有些客户建表是存在uuid的,如果存在uuid一定要比对保证地址一样不然无法恢复数据。
ReplicatedReplacingMergeTree('/clickhouse/tables/3/xxxx/xxxxx', '{replica}', created_time)
shell> vim init_table.sql
重建表并确认表是否同步数据。
shell>clickhouse-client --password --port 9000 --multiquery < init_table.sql
检查表的数据是否正确这里总共 22 张本地表,存于在 3 个库。
经过验证已经全部重建完毕,现在验证数据是否传输。
clickhouse-2>use database clickhouse-2>select * from xxxx limit 5;
检查磁盘的同步情况。
shell>df -h
数据一直同步每分钟数据量大概 10GB 的速度同步回来。
恢复分布式总表
shell>clickhouse-client --password --host=xxx.xxx.77.30 --port=9000 clickhouse-1>select create_table_query from system.tables a where a.database in ('xxx','xxx','xxx') and engine='Distributed';
创建分布式表的初始化 SQL 文件。
shell>vim init_d_table.sql
同步。
shell>clickhouse-client --password --port 9000 --multiquery < init_d_table.sql
检查分布式总表是否全部创建总共 22 张。
clickhouse-2>select count(1) from system.tables a where a.database in ('xxx','xxx','xxx') and engine='Distributed';
查询分布式总表看看是否有数据。
通过其他副本验证同步复制关系是否正常
shell>clickhouse-client --password --host=xxx.xxx.77.30 --port=9000 clickhouse-1>select database,table,replica_is_active from system.replicas;
已经通过验证所有表已经全部恢复同步。
总结与启示
本次 ClickHouse 数据恢复案例展示了以下具体技术关键点:
- 数据冗余备份:
- 确保每个分片有多个副本,防止单点故障导致数据丢失。
- 掌握 ClickHouse 和 Zookeeper 同步机制:
- 了解如何通过 Zookeeper 获取其他副本的 parts 路径,并使用端口
9009
进行数据传输恢复。
- 清理 Zookeeper 元数据:
- 在磁盘损坏后,需清理 Zookeeper 中的元数据,以避免重建表时发生元数据冲突。
- 详细的恢复操作步骤:
- 导出表结构并创建数据库。
- 使用create_table_query重建表并确认数据同步。
- 检查磁盘同步情况,确保数据正确恢复。
- 持续监控与维护:
- 定期检查系统状态,及时发现并解决潜在问题,确保系统高可用性。
这些经验和具体操作步骤能有效提高系统的可靠性和运维效率,增强应对突发故障的能力。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
✨ Github:https://github.com/actiontech/sqle
?* 文档:https://actiontech.github.io/sqle-docs/
?* 官网:https://opensource.actionsky.com/sqle/
?* 微信群:请添加小助手加入 ActionOpenSource
?* 商业支持:https://www.actionsky.com/sqle

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
得物SRE K8s 故障诊断:从 CPU 高负载到挂载泄露根源揭示
一、背景 现代软件部署中,容器技术已成为不可或缺的一环,在云计算和微服务架构中发挥着核心作用。随着容器化应用的普及,确保容器环境的可靠性成为了一个至关重要的任务。这就是容器SRE(Site Reliability Engineering,站点可靠性工程)的职责所在。容器SRE工程师不仅要保证系统的高可用性,还需要优化运行效率,确保系统在各种压力和突发情况下的韧性。 然而,容器SRE的工作常常是背后默默的付出,通常涉及着大量看似琐碎却极其关键的维护任务。例如某一天,你可能发现K8s集群中的Kubelet进程CPU使用异常飙高,这就需要容器SRE工程师立即介入,进行深入的诊断和问题排查,避免类似问题成为生产环境中的隐患。这种排查过程往往涉及复杂且难以预测的环境,通常需要SRE工程师具备高度的专业知识和快速应变能力。因此,虽然容器SRE工程师的努力可能不为大众所见,但对于现代依赖软件和云服务的任何系统来说,这些工作显得尤为严谨和重要。 通过本文,我们将深入探讨容器SRE在日常工作中面临的挑战和如何通过专业技能和创新技术方案来定位和解决问题,确保技术平台的稳健运行。这些看似“摸不着头脑”的琐碎...
- 下一篇
v5内存分配器性能优化
背景 在之前我们提到采用自定义的内存分配器来解决防止频繁 make 导致的 gc 问题。gc 问题本质上是 CPU 消耗,而内存分配器本身如果产生了大量的 CPU 消耗那就得不偿失。经过测试初代内存分配器实现过于简单,产生了很多 CPU 消耗,因此必须优化内存分配器的性能。 性能消耗原因 在内存的分配和回收上,使用了简单的循环检测,当内存碎片较多的时候,循环查找消耗非常可观 查找可分配的内存 找到回收的内存偏移 性能优化 很快在社区中大家给出了一个称为 Buddy 的内存分片算法,那么这个算法是否能解决问题呢? Buddy 算法 这是一个非常高效的算法,采用的是满二叉树数据结构,用一个数组来表示,然而当实际使用时却遇到了问题,因为我需要在自研的 BufReader 中使用,因此不能出现内存缝隙。Buffdy 算法在回收内存时只能按照申请什么回收什么的原则。举例,我申请了一个var a []byte = alloc(100),那么回收必须也是回收 free(a)。而自研的 BufReader,需要“部分回收”能力。比如先回收a[50:],然后再回收a[:50]。那么 Buddy 算法将无...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Mario游戏-低调大师作品
- Linux系统CentOS6、CentOS7手动修改IP地址
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境