大数据 -141 ClickHouse 副本实战 | ReplicatedMergeTree + ZooKeeper 从 0–1:创建、选举、日志复制、排障

TL;DR
场景:两台以上 ClickHouse 节点做同步副本,要求写入可在任意副本执行且最终一致。
结论:按本文 SOP,你能在 10–15 分钟完成副本创建、日志复制校验与故障回滚。
产出:配置文件、整个过程、ON CLUSTER DDL、排障速查等。
副本介绍
ReplicatedMergeTreeZooKeeper:实现多个实例之间的通信。
副本的特点
作为数据副本的主要载体,ReplicatedMergeTree 在设计上有一些缺点:
依赖 ZooKeeper: 在执行 INSERT 和 ALTER 查询的时候,ReplicatedMergeTree 需要借助 ZooKeeper 的分布式协同功能,以实现多个副本之间的同步。但是在查询副本的时候,并不需要 ZooKeeper。
表级别的副本:副本是在表级别定义的,所以每张表的副本配置都可以按照它的实际需求进行个性化定义,包括副本的数量,以及副本在集群内的分布位置等。
多主架构(Multi Master):可以在任意一个副本上执行 INSERT 和 ALTER 查询,他们效果是相同的,这些操作会借助 ZooKeeper 的协同能力被分发至每个副本以本地的形式执行。
Block 数据块,在执行 INSERT 命令写入数据时,会依据 max_block_size 的大小(默认 1048576 行)将数据切分成 若干个 Block 数据块。所以 Block 数据块是数据写入的基本单元,并且具有写入的原子性和唯一性。
原子性:在数据写入时,一个 Block 块内的数据要么全部写入成功,要不全部失败。
唯一性:在写一个 Block 数据块的时候,会按照当前 Block 数据块的数据顺序、数据行和数据大小等指标,计算 Hash 信息摘要并记录在案。在此之后,如果某个待写入的 Block 数据块与先前被写入的 Block 数据块拥有相同的 Hash 摘要(Block 数据块内数据顺序、数据大小和数据行均相同),则该 Block 数据块会被忽略,这项设计可以预防由异常原因引起的 Block 数据块重复写入问题。
ZK 的配置
之前配置之前章节我们已经配置过了 ZK,配置好了集群模式。这里简单提一下,如果你没有做好,你需要回去之前的章节完成。
开启 ZK
但是我们没有开启 ZK,我们需要在配置文件中开启:
配置结果如下图所示:
重启服务
检验结果
接着执行 SQL 检查是否成功链接到了 ZooKeeper
执行结果如下图,如果你也是这样的没有报错,说明配置 ZooKeeper 服务成功!
集群配置
如果有需要,记得将其他的节点都按照如上配置方式配置完毕。
副本定义形式
创建新表
/clickhouse/tables 约定俗成的路径
/01/ 分片编号
replicated_sales_5 数据表的名字 建议与物理表名字相同
h121.wzk.icu 在 ZK 中创建副本的名称,约定俗成是服务器的名称
执行结果如下图所示:
查询结果
可以检查刚才的操作结果:
执行结果内容如下:
查看 ZK
进入到 ZK 中,对数据进行查看:
执行结果如下图所示:
ReplicatedMergeTree 原理
数据结构
元数据:
metadata:元数信息 主键、采样表达式、分区键
columns:列的字段的数据类型、字段名
replicats:副本的名称
标志:
leader_eletion:主副本的选举路径
blocks:hash 值(复制数据重复插入)、partition_id
max_insert_block_size: 1048576 行
block_numbers:在同一分区下 block 的顺序
quorum:副本的数据量
操作类:
log:log-000000 常规操作
mutations:delete update
创建新表 1
在当前机器上建立新表:
根据 zk_path 初始化所有的 zk 节点
在 replicas 节点下注册自己的副本实例 h121.wzk.icu
启动监听任务 监听 LOG 日志节点
参与副本选举,选出主副本,选举的方式是向 leader_election 插入子节点,第一个插入成功的副本就是主副本
执行结果如下图所示:
创建新表 2
创建第二个副本实例(注意,当前我们需要连接到 h122 节点上):
执行对应的 SQL:
执行的结果如下图所示:
此时参与副本选举,h121.wzk.icu 副本成为了主副本。
插入数据 1
目前我们在 h121.wzk.icu 插入数据:
执行上述内容结果为:
查看结果
执行完后,我们在 ZK 上查看数据:
输出了如下的内容,插入命令执行后,在本地完成分区的目录的写入,接着向 Block 写入该分区的 block_id:
查看日志
接下来,h121.wzk.icu 副本发起向 log 日志推送操作日志:
再次插入一条数据:
查看 LOG 日志:
输出内容如下:
拉取日志
接下来,第二个副本拉取 Log 日志:h122.wzk.icu 节点会一直监听 /log 节点的变化,当 h121.wzk.icu 推送了/log/log-000000、0000001 之后,h122.wzk.icu 节点便会触发日志的拉取任务,并更新 log_pointer。
执行结果如下图所示:
错误速查
其他系列
🚀 AI 篇持续更新中(长期更新)
AI 炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究,持续打造实用 AI 工具指南!AI-调查研究-108-具身智能 机器人模型训练全流程详解:从预训练到强化学习与人类反馈🔗 AI模块直达链接
💻 Java 篇持续更新中(长期更新)
Java-154 深入浅出 MongoDB 用 Java 访问 MongoDB 数据库 从环境搭建到 CRUD 完整示例 MyBatis 已完结,Spring 已完结,Nginx 已完结,Tomcat 已完结,分布式服务正在更新!深入浅出助你打牢基础!🔗 Java模块直达链接
📊 大数据板块已完成多项干货更新(300 篇):
包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT 案例 详解🔗 大数据模块直达链接
版权声明: 本文为 InfoQ 作者【武子康】的原创文章。
原文链接:【http://xie.infoq.cn/article/61518c1d1529138287623f773】。文章转载请联系作者。







评论