文章目录

  • ReplicatedMergeTree引擎
    • 特点
    • 数据结构
      • ZooKeeper内的节点结构
      • Entry日志对象的数据结构
    • 副本协同的核心流程
      • INSERT
      • MERGE
      • MUTATION
      • ALTER

ReplicatedMergeTree引擎

ReplicatedMergeTree是MergeTree的派生引擎,它在MergeTree的基础上加入了分布式协同的能力,只有使用了ReplicatedMergeTree复制表系列引擎,才能应用副本的能力。或者用一种更为直接的方式理解,即使用ReplicatedMergeTree的数据表就是副本

ReplicatedMergeTree与MergeTree的逻辑关系

在MergeTree中,一个数据分区由开始创建到全部完成,会历经两类存储区域。

  • 内存:数据首先会被写入内存缓冲区。
  • 本地磁盘:数据接着会被写入tmp临时目录分区,待全部完成后再将临时目录重命名为正式分区。

ReplicatedMergeTree在上述基础之上增加了ZooKeeper的部分,它会进一步在ZooKeeper内创建一系列的监听节点,并以此实现多个实例之间的通信。在整个通信过程中,ZooKeeper并不会涉及表数据的传输。

特点

作为数据副本的主要实现载体,ReplicatedMergeTree在设计上有一些显著特点。

  • 依赖ZooKeeper:在执行INSERTALTER查询的时候,ReplicatedMergeTree需要借助ZooKeeper的分布式协同能力,以实现多个副本之间的同步。但是在查询副本的时候,并不需要使用ZooKeeper。

  • 表级别的副本:副本是在表级别定义的,所以每张表的副本配置都可以按照它的实际需求进行个性化定义,包括副本的数量,以及副本在集群内的分布位置等。

  • 多主架构(Multi Master):可以在任意一个副本上执行INSERTALTER查询,它们的效果是相同的。这些操作会借助ZooKeeper的协同能力被分发至每个副本以本地形式执行。

  • Block数据块:在执行INSERT命令写入数据时,会依据max_insert_block_size的大小(默认1048576行)将数据切分成若干个Block数据块。所以Block数据块是数据写入的基本单元,并且具有写入的原子性和唯一性。

  • 原子性:在数据写入时,一个Block块内的数据要么全部写入成功,要么全部失败。

  • 唯一性:在写入一个Block数据块的时候,会按照当前Block数据块的数据顺序、数据行和数据大小等指标,计算Hash信息摘要并记录在案。在此之后,如果某个待写入的Block数据块与先前已被写入的Block数据块拥有相同的Hash摘要(Block数据块内数据顺序、数据大小和数据行均相同),则该Block数据块会被忽略。

数据结构

ZooKeeper内的节点结构

ReplicatedMergeTree需要依靠ZooKeeper的事件监听机制以实现各个副本之间的协同。所以,在每张ReplicatedMergeTree表的创建过程中,它会以zk_path为根路径,在ZooKeeper中为这张表创建一组监听节点。

按照作用的不同,监听节点可以大致分成如下几类:

  • 元数据

    • /metadata:保存元数据信息,包括主键、分区键、采样表达式等。
    • /columns:保存列字段信息,包括列名称和数据类型。
    • /replicas:保存副本名称,对应设置参数中的replica_name
  • 判断标识
    • /leader_election:用于主副本的选举工作,主副本会主导MERGEMUTATION操作(ALTER DELETEALTER UPDATE)。这些任务在主副本完成之后再借助ZooKeeper将消息事件分发至其他副本。
    • /blocks:记录Block数据块的Hash信息摘要,以及对应的partition_id。通过Hash摘要能够判断Block数据块是否重复;通过partition_id,则能够找到需要同步的数据分区。
    • /block_numbers:按照分区的写入顺序,以相同的顺序记录partition_id。各个副本在本地进行MERGE时,都会依照相同的block_numbers顺序进行。
    • /quorum:记录quorum的数量,当至少有quorum数量的副本写入成功后,整个写操作才算成功。quorum的数量由insert_quorum参数控制,默认值为0。
  • 操作日志
    • /log:常规操作日志节点(INSERTMERGEDROP PARTITION),它是整个工作机制中最为重要的一环,保存了副本需要执行的任务指令。log使用了ZooKeeper的持久顺序型节点,每条指令的名称以log-为前缀递增,例如log-0000000000、log-0000000001等。每一个副本实例都会监听/log节点,当有新的指令加入时,它们会把指令加入副本各自的任务队列,并执行任务。
    • /mutations:MUTATION操作日志节点,作用与log日志类似,当执行ALERT DELETEALERT UPDATE查询时,操作指令会被添加到这个节点。mutations同样使用了ZooKeeper的持久顺序型节点,但是它的命名没有前缀,每条指令直接以递增数字的形式保存,例如0000000000、0000000001等。
    • /replicas/{replica_name}/*:每个副本各自的节点下的一组监听节点,用于指导副本在本地执行具体的任务指令,其中较为重要的节点有如下几个:
      • /queue:任务队列节点,用于执行具体的操作任务。当副本从/log或/mutations节点监听到操作指令时,会将执行任务添加至该节点下,并基于队列执行。
      • /log_pointer:log日志指针节点,记录了最后一次执行的log日志下标信息。
      • /mutation_pointer:mutations日志指针节点,记录了最后一次执行的mutations日志名称。

Entry日志对象的数据结构

ReplicatedMergeTree在ZooKeeper中有两组非常重要的父节点,那就/log/mutations。它们的作用犹如一座通信塔,是分发操作指令的信息通道,而发送指令的方式,则是为这些父节点添加子节点。

所有的副本实例,都会监听父节点的变化,当有子节点被添加时,它们能实时感知。这些被添加的子节点在ClickHouse中被统一抽象为Entry对象,而具体实现则由LogEntry和MutationEntry对象承载,分别对应/log/mutations节点

  • LogEntry

    • source replica:发送这条Log指令的副本来源,对应replica_name。
    • type:操作指令类型,主要有getmergemutate三种,分别对应从远程副本下载分区、合并分区和MUTATION操作。
    • block_id:当前分区的BlockID,对应/blocks路径下子节点的名称。
    • partition_name:当前分区目录的名称。
  • MutationEntry
    • source replica:发送这条MUTATION指令的副本来源,对应replica_name。
    • commands:操作指令,主要有ALTER DELETEALTER UPDATE
    • mutation_id:MUTATION操作的版本号。
    • partition_id:当前分区目录的ID。

副本协同的核心流程

副本协同的核心流程主要有INSERTMERGEMUTATIONALTER四种,分别对应了数据写入、分区合并、数据修改和元数据修改。INSERTALTER是分布式执行的,借助ZooKeeper的事件通知机制,多个副本之间会自动进行有效协同,但是它们不会使用ZooKeeper存储任何分区数据。而其他操作并不支持分布式执行,包括SELECTCREATEDROPRENAMEATTACH

在下列例子中,使用ReplicatedMergeTree实现一张拥有1分片、1副本的数据表来分别执行INSERTMERGEMUTATIONALTER操作,演示执行流程。

INSERT

当需要在ReplicatedMergeTree中执行INSERT查询以写入数据时,即会进入INSERT核心流程,它的核心流程如下图所示

INSERT的核心执行流程

  1. 向副本A写入数据
  2. 由副本A推送Log日志
  3. 各个副本拉取Log日志
  4. 各个副本向远端副本发起下载请求
    • 选择一个远端的其他副本作为数据的下载来源。远端副本的选择算法大致是这样的:

      • /replicas节点拿到所有的副本节点。
      • 遍历这些副本,选取其中一个。选取的副本需要拥有最大的log_pointer下标,并且/queue子节点数量最少。log_pointer下标最大,意味着该副本执行的日志最多,数据应该更加完整;而/queue最小,则意味着该副本目前的任务执行负担较小。
  5. 远端副本响应其它副本的数据下载
  6. 各个副本下载数据并完成本地写入

INSERT的写入过程中,ZooKeeper不会进行任何实质性的数据传输。本着谁执行谁负责的原则,在这个案例中由CH5首先在本地写入了分区数据。之后,也由这个副本负责发送Log日志,通知其他副本下载数据。如果设置了insert_quorum并且insert_quorum>=2,则还会由该副本监控完成写入的副本数量。其他副本在接收到Log日志之后,会选择一个最合适的远端副本,点对点地下载分区数据。

MERGE

当ReplicatedMergeTree触发分区合并动作时,即会进入这个部分的流程,它的核心流程如下图所示

MERGE的核心执行流程

无论MERGE操作从哪个副本发起,其合并计划都会交由主副本来制定。

  1. 创建远程连接,尝试与主副本通信
  2. 主副本接收通信
  3. 由主副本制定MERGE计划并推送Log日志
  4. 各个副本分别拉取Log日志
  5. 各个副本分别在本地执行MERGE

可以看到,在MERGE的合并过程中,ZooKeeper也不会进行任何实质性的数据传输,所有的合并操作,最终都是由各个副本在本地完成的。而无论合并动作在哪个副本被触发,都会首先被转交至主副本,再由主副本负责合并计划的制定、消息日志的推送以及对日志接收情况的监控。

MUTATION

当对ReplicatedMergeTree执行ALTER DELETE或者ALTER UPDATE操作的时候(ClickHouse把DELETEUPDATE操作也加入到了ALTER TABLE的范畴中,它并不支持裸的DELETE或者UPDATE操作),即会进入MUTATION部分的逻辑

MUTATION的核心执行流程

MERGE类似,无论MUTATION操作从哪个副本发起,首先都会由主副本进行响应。

  1. 推送MUTATION日志
  2. 所有副本实例各自监听MUTATION日志
  3. 由主副本实例响应MUTATION日志并推送Log日志
  4. 各个副本实例分别拉取Log日志
  5. 各个副本实例分别在本地执行MUTATION

MUTATION的整个执行过程中,ZooKeeper同样不会进行任何实质性的数据传输。所有的MUTATION操作,最终都是由各个副本在本地完成的。而MUTATION操作是经过/mutations节点实现分发的。CH6负责了消息的推送。但是无论MUTATION动作从哪个副本被触发,之后都会被转交至主副本,再由主副本负责推送Log日志,以通知各个副本执行最终的MUTATION逻辑。同时也由主副本对日志接收的情况实行监控。

ALTER

当对ReplicatedMergeTree执行ALTER操作进行元数据修改的时候,即会进入ALTER部分的逻辑,例如增加、删除表字段等,核心流程如下图

ALTER的核心执行流程

ALTER的流程与前几个相比简单很多,其执行过程中并不会涉及/log日志的分发,整个流程大致分成3个步骤

  1. 修改共享元数据
  2. 监听共享元数据变更并各自执行本地修改
  3. 确认所有副本完成修改

ALTER整个的执行过程中,ZooKeeper不会进行任何实质性的数据传输。所有的ALTER操作,最终都是由各个副本在本地完成的。本着谁执行谁负责的原则,在这个案例中由CH6负责对共享元数据的修改以及对各个副本修改进度的监控。

ClickHouse 副本协同原理:ReplicatedMergeTree引擎相关推荐

  1. ClickHouse源码阅读(0000 0110) —— 使用ReplicatedMergeTree引擎时的副本选择问题

    在使用ReplicatedMergeTree引擎和Distributed引擎的时候,对于同一张表,服务器上存在多个副本,在查询数据的时候,是如何在这些副本之间进行选择的呢?结合源码来试着分析一下... ...

  2. ClickHouse副本表ReplicatedMergeTree实操

    不适用的场景 首先副本表无法实现下图的设计,这是因为clickhouse中的副本是一张实实在在的物理表,而你不能在一台clickhouse服务器上创建两个相同的表 我们可以尝试一下,三分片一副本,按照 ...

  3. Docker下运行两个ClickHouse容器后 ReplicatedMergeTree引擎借助Zookeeper将数据无法同步的解决方案,提示错误为“DNS_ERROR”

    前置准备 目的 依照官网对ReplicatedMergeTree引擎的创建方式Docker服务下运行两个ClickHouse容器,分别修改CK的config.xml文件使其能顺利连通Zookeeper ...

  4. 【大数据 OLAP ClickHouse 引擎】ClickHouse 系统架构和存储引擎实现原理 : 为什么 ClickHouse 这么快? Why is ClickHouse so fast?

    文章目录 ClickHouse 系统架构和存储引擎实现原理 ClickHouse 简介 ClickHouse 整体架构 & 核心模块 1. Column与Field 2. DataType 3 ...

  5. ClickHouse之ReplicatedMergeTree引擎介绍

    Replicated 副本的意思,副本可以让我们的服务高可用 1 什么是ClickHouse的副本: 两个相同数据的表, 作用是为了数据备份与安全,保障数据的高可用性 副本是表级别的,不是整个服务器级 ...

  6. clickHouse副本和同步机制

    文章目录 1. 副本的基本概念 1. 1 什么是副本 1. 2 副本写入流程简单示例 1. 3 多副本的配置 1. 4 clickhouse创建副本表 2. 副本同步原理 2.1 clickhouse ...

  7. clickhouse副本和分片

    title: clickhouse副本和分片 date: 2021-02-20 16:48:02 categories: 数据库 tags: clickHouse 副本和分片是在很多分布式系统中都有, ...

  8. 【clickhouse】clickhouse 副本与分片 分片详解

    1.概述 转载:[clickhouse]clickhouse 副本与分片 分片详解 clickhouse 中每个服务器节点都可以被称为一个 shard(分片). 假设有 N 台服务器,每个服务器上都有 ...

  9. 2022-10-24 ClickHouse 源码解析-查询引擎经典理论

    ClickHouse 源码解析: 综述 ClickHouse 源码解析: MergeTree Write-Path ClickHouse 源码解析: MergeTree Read-Path Click ...

最新文章

  1. java8的jvm优化_基于JDK8 版本的SpringBoot 启动参数优化(建议收藏)
  2. 施一公:优秀博士如何养成(全文) 清华大学演讲
  3. luoguP4503 [CTSC2014]企鹅QQ hash
  4. Leetcode 125. 验证回文串 (每日一题 20210816)
  5. POST 变为AJAX提交代码。
  6. 给服务器装系统U盘要处理吗,服务器装系统从u盘装
  7. 你好,同学!在云端学习最潮的技术吧!
  8. 用c++写的一个词典工具
  9. 现代程序设计 作业 第1次
  10. python中怎样创建字典内建函数_python中常用的字典内建函数
  11. HDFS QJM机制分析
  12. 【JAVA SE】第八章 异常处理与抽象类
  13. 贪心---区间覆盖问题(水题)
  14. 【渝粤教育】电大中专跨境电子商务理论与实务 (8)作业 题库
  15. UE4安装教程,虚幻引擎安装教程,UE4的安装
  16. 计算机无法添加用户名或密码错误,win10系统无法登录网络打印机提示未知的用户名或者密码错误的设置技巧...
  17. Raspberry Pi 上手准备
  18. 《关于我横扫一线厂的那些面经》拼多多Java岗(附答案)
  19. 不换行输出的两种方式
  20. linux下eclipse开发storm,如何在eclipse调试storm程序?

热门文章

  1. 手动使用cglib代理(了解)
  2. spring配置详解-属性注入(p名称空间SPEL表达式)
  3. Spring核心系列之Spring中的事务
  4. html2canvas截图页面中某块区域的图不全_截图操作千千万,唯舒适最重要!你更Pick谁?...
  5. mysql的主键有什么作用_mysql设置主键有什么用
  6. Jlink无法识别CPU/lpc2103/lpc2131
  7. 人工智能化发展已经到了哪一步?
  8. 一个产品经理的自述:我在腾讯工作的这一年(转)
  9. linux命令(8)kill命令
  10. 远程桌面退出全屏/不能全屏/全屏切换的技巧