Clickhouse分布式表引擎(Distributed)写入核心原理解析

news2024/9/21 15:29:37

Clickhouse分布式表引擎(Distributed)写入核心原理解析

  • Clickhouse分布式表引擎(Distributed)写入核心原理解析
  • Clickhouse分布式表引擎(Distributed)查询核心原理解析

Distributed表引擎是分布式表的代名词,它自身不存储任何数据,而是作为数据分片的透明代理,能够自动路由数据至集群中的各个节点,所以Distributed表引擎需要和其他数据表引擎一起协同工作。

从实体表层面来看,一张分片表由两部分组成:

  • 本地表:通常以_local为后缀进行命名。本地表是承载数据的载体,可以使用非Distributed的任意表引擎,一张本地表对应了一个数据分片。
  • 分布式表:通常以_dist为后缀进行命名。分布式表只能使用Distributed表引擎,它与本地表形成一对多的映射关系,日后将通过分布式表代理操作多张本地表。

对于分布式表与本地表之间表结构的一致性检查,Distributed表引擎采用了读时检查的机制,这意味着如果它们的表结构不兼容,只有在查询时才会抛出错误,而在创建表时并不会进行检查。

定义形式

Distributed表引擎的定义形式如下所示:

ENGINE = Distributed(cluster, database, table, [,sharding_key])

其中,各个参数的含义分别如下:

  • cluster:集群名称,与集群配置中的自定义名称相对应。在对分布式表执行写入和查询的过程中,它会使用集群的配置信息来找到相应的host节点。
  • database和table:分别对应数据库和表的名称,分布式表使用这组配置映射到本地表。
  • sharding_key:分片键,选填参数。在数据写入的过程中,分布式表会依据分片键的规则,将数据分布到各个host节点的本地表。

比如如下分布式表:

CREATE TABLE test_shard_dist on cluster ch_cluster(
    `id` Int8
) ENGINE=Distributed('ch_cluster', 'test', 'test_shard_local', rand());

上述建表语句将分片键指定为rand()函数,此时在数据写入时会根据随机函数的取值决定数据写入哪个分片。

值得注意的是,此时对应的本地表还未创建,所以从这里也可以看出来,Distributed表运用的是读时检查的机制,对创建分布式表和本地表的顺序并没有强制要求。

接着,创建本地表,一张本地表代表着一个数据分片。

CREATE TABLE test_shard_local on cluster ch_cluster(
    `id` Int8
)ENGINE=MergeTree()
order by id
partition by id

在本次案例中,我们的ch_cluster由三个节点组成,因此会在三个节点上都创建出对应的本地表和分布式表。

分布式写入的核心流程

在向集群内的分片写入数据时,通常有两种思路:一种是借助外部计算系统,事先将数据均匀分片,再借由计算系统直接将数据写入Clickhouse集群的各个本地表。如下图所示:

在这里插入图片描述

在这个流程中,继续使用集群ch_cluster的示例,该集群由2个分片和0个副本组成。整个流程从上至下按照时间顺序进行,其大致分为5个步骤:

(1)在第一个分片节点写入本地分片数据

首先在Linux121节点,对分布式表test_shard_dist执行INSERT查询,尝试写入10、30、200、55四行数据。

执行后分布式表主要会做两件事情:

  1. 根据分片规则划分数据,将不同的数据标记划分给不同的节点插入。
  2. 将属于当前分片的数据直接写入本地表test_shard_local

(2)第一个分片建立远端连接,准备发送远端分片数据

将归至远端分片的数据以分区为单位,分别写入test_shard_all存储目录下的临时bin文件,如下图所示:

在这里插入图片描述

这里的1.bin是一个[increase_num].bin,有几个shard分片,则依次递增。

(3)第一个分片向远端分片发送数据

此时,Clickhouse会有另一组监听任务负责监听/test_shard_dist目录下的文件变化,这些任务负责将目录数据发送至远端分片。

<Debug> test.test_shard_dist.DirectoryMonitor: Started processing `/var/lib/clickhouse/data/test/test_shard_dist/shard2_replica1/1.bin` (2.00 rows, 2.00 B bytes)

<Debug> test.test_shard_dist.DirectoryMonitor: Started processing `/var/lib/clickhouse/data/test/test_shard_dist/shard3_all_replicas/2.bin` (2.00 rows, 2.00 B bytes)

从Linux121节点的Clickhouse日志中我们可以看到,其负责将分片数据发送到对应的远端节点上。我这里一共有三个节点,所以Linux121节点将分片数据发往对应的Linux122、Linux123节点,分别对应数据块1.bin和2.bin。

其中需要注意的是,每份目录将会由独立的线程负责发送,数据在传输之前会被压缩。

(4)第二个分片接收数据并写入本地

Linux122和Linux123节点确认建立与Linux121的连接

<Trace> Connection (linux121:9000): Connected to ClickHouse server version 22.4.6.

在接收到来自Linux121节点发送的数据后,将它们写入本地表中

Linux122节点服务日志:

<Debug> executeQuery: (from [::ffff:192.168.80.121]:56626, initial_query_id: 8579dc90-d839-4e63-8442-b31a8c7fe6cf) INSERT INTO test.test_shard_local (id) VALUES
<Trace> ContextAccess (default): Access granted: INSERT(id) ON test.test_shard_local
<Trace> test.test_shard_local (e43a2707-58a8-4bfb-8615-d9b175debdfe): Renaming temporary part tmp_insert_10_1_1_0 to 10_1_1_0

Linux123节点服务日志:

<Debug> executeQuery: (from [::ffff:192.168.80.121]:44996, initial_query_id: 8579dc90-d839-4e63-8442-b31a8c7fe6cf) INSERT INTO test.test_shard_local (id) VALUES
<Trace> ContextAccess (default): Access granted: INSERT(id) ON test.test_shard_local
 <Trace> test.test_shard_local (e43a2707-58a8-4bfb-8615-d9b175debdfe): Renaming temporary part tmp_insert_-56_1_1_0 to -56_1_1_0.

接收数据–>执行写入命令->重命名临时分区->实际分区(这里原表是按id作为分区的,所以是-56_1_1_0)

(5)由第一个分片确认完成写入

最后,还是由Linux121节点确认所有的数据发送完毕:

 <Trace> test.test_shard_dist.DirectoryMonitor: Finished processing `/var/lib/clickhouse/data/test/test_shard_dist/shard2_replica1/1.bin` (took 5 ms)
 
  <Trace> test.test_shard_dist.DirectoryMonitor: Finished processing `/var/lib/clickhouse/data/test/test_shard_dist/shard3_all_replicas/2.bin` (took 5 ms)

至此,整个流程结束。

可以看到,在整个流程中,Distributed表负责所有分片的写入工作。本着谁执行谁负责的原则,在这个示例中,由Linux121节点的分布式表负责切分数据,并向所有其他分片节点发送数据。

在由Distributed表负责向远端分片发送数据时,有异步写入和同步写入两种模式:如果是异步写,则在Distributed表写完本地分片之后,INSERT查询就会返回成功写入的信息。如果是同步写,则在执行INSERT查询之后,会等待所有分片完成写入。

使用何种模式由参数insert_distributed_sync参数控制,默认为false,即为异步写。如果将其设置为true,则可以进一步通过insert_distributed_timeout参数控制同步等待的超时时间。

分布式写入时副本复制数据的核心流程

如果在集群的配置中包含了副本,那么除了刚才的分片写入流程之外,还会触发副本数据的复制流程。数据在多个副本之间,有两种复制实现方式:一种是继续借助Distributed表引擎,由它将数据写入副本。另一种则是借助ReplicatedMergeTree表引擎实现副本数据的分发。

在这里插入图片描述

(1)通过Distributed复制数据

在这种实现方式下,即使本地表不使用ReplicatedMergeTree表引擎,也能实现数据副本的功能。Distributed会同时负责分片和副本的数据写入工作,而副本数据的写入流程与分片逻辑相同。

比如对于下面的配置

<!-- 1个分片,1个副本 -->
<ch_cluster>
    <shard>
        <replica>
            <host>linux121</host>
            <port>9000</port>
        </replica>
        <replica>
            <host>linuxxxx</host>
            <port>9000</port>
        </replica>
    </shard>
</ch_cluster>

Linux121和linuxxxx互为副本,此时,按照上面介绍分布式数据写入的逻辑,Linux121的分布式表不仅负责将数据写入本地,还需要负责将数据发往副本所在的节点。

总结,用这种方式时,向Distributed表写入数据,它会负责将数据写入集群内的每个replica

细心的朋友应该能发现,在这种实现方案下,Distributed节点需要同时负责分片和副本的数据写入工作,它很可能会成为写入的单点瓶颈, 所有就有了接下来将要说明的第二种方案。

(2)通过ReplicatedMergeTree复制数据

如果在集群的shard配置中增加internal_replication参数并将其设置为true(默认为false),那么Distributed表在该shard中只会选择一个合适的replica并对其写入数据。此时,如果使用ReplicatedMergeTree作为本地表的引擎,则在该shard内,多个replica副本之间的数据复制会交由ReplicatedMergeTree自己处理,不再由Distributed负责,从而为其减负。

在shard中选择replica的算法大致如下:首选,在Clickhouse的服务节点中,拥有一个全局及数据器errors_count。当服务出现任何异常时,该计数器累加1。接着,当一个shard内拥有多个replica时,选择errors_count错误最少的那个。

至此,我们介绍了关于Clickhouse使用分布式表写入的核心流程原理和副本复制原理。

但是在此还是需要注意,通过上面我们介绍可以知道,在使用Distributed表引擎写入时,由分布式表写入的节点负责将数据分片,并发送到集群中的其他节点中,这种情况在数据量比较大时,很有可能造成写入的单点瓶颈。同时加重网络中传输的数据量,容易造成网络拥塞。因此,在实际生产中,更建议直接写本地表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/467421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue打包并部署到nginx上

一、打包vue项目 打包的命令依据项目的配置可能会有所不同&#xff0c;打包的命令可以在package.json中查看 项目中vue.config.js中的配置如下&#xff1a; proxy关系到我们项目部署到nginx上需要配置对应的反向代理 publicPath关系到我们部署时是否需要配置子路径 默认情况…

基于公共信箱的全量消息实现

作者 | 百度消息中台团队 导读 消息中台为百度App以及厂内百度系产品提供即时通讯的能力&#xff0c;提供包括私聊、群聊、聊天室、直播弹幕等用户沟通场景&#xff0c;并帮助业务通过消息推送触达用户。百度App存在需要以『低用户打扰』的形式触达全量用户的场景&#xff0c;而…

AcWing第 96 场周赛

竞赛 - AcWing 一、完美数 4876. 完美数 - AcWing题库 1、题目 如果一个正整数能够被 2520 整除&#xff0c;则称该数为完美数。 给定一个正整数 n&#xff0c;请你计算 [1,n]范围内有多少个完美数。 输入格式 一个整数 n。 输出格式 一个整数&#xff0c;表示 [1,n] 范…

C++:Article : 链接器(三):库与可执行文件的生成

链接器&#xff1a;库与可执行文件 1. 静态库1.1 静态链接下&#xff0c;可执行文件如何生成 2. 动态库2.1 动态库特点以及与静态库使用方式差异2.2 动态库和静态库使用时间 3. load-time dynamic linking&#xff08;加载时动态链接&#xff09;3.1&#xff1a;阶段一&#xf…

【工具】FFmpeg|超大视频本地有损压缩,500MB变25MB(支持 Windows、Linux、macOS)

参考&#xff1a; 如何将一分钟长的1080p视频压缩至5MB以内&#xff1f;-知乎-滔滔清风近期HEVC扩展备用安装方法-B站-悲剧天下 总共三个步骤&#xff0c;安装FFmpeg、运行指令、打开视频。 亲测 500MB 变 25MB。 1 安装FFmpeg 对于不需要看教程可以自行完成安装的同学们&am…

MySQL基础案例——数据表的基本操作:创建表和修改表

目录 案例目的&#xff1a; 创建表&#xff1a; 创建offices&#xff1a; 创建employees表&#xff1a; 修改表&#xff1a; 将 employees 的 mobile 字段移动到 officeCode 字段后&#xff1a; 将 birth 字段名称改为 employee_birth: 修改 sex 字段&#xff0c;数据类…

TryHackMe-Looking Glass(boot2root)

Looking Glass 穿过镜子。仙境挑战室的续集。 端口扫描 循例nmap 又是一堆ssh&#xff0c;跟之前的玩法一样 找到正确的ssh端口之后后给了一段密文&#xff0c;要求输入secret才能进入ssh 这看起来非常像凯撒密码 唯一可识别的信息是Jabberwocky&#xff0c;我们找到了它 它…

IDA简单使用

今天来简单介绍一下逆向中常用到的另一个静态分析工具IDA&#xff0c;还是昨天那个打印demo&#xff08;64位&#xff09;&#xff1a; #include #include char a[] "https://www.vultop.com/"; int main(int argc, char* argv[]) { printf("%s", a)…

什么是微服务

目录 一、微服务介绍 1. 什么是微服务 2. 微服务由来 3. 为什么需要微服务&#xff1f; 3.1 最期的单体架构带来的问题 3.2 微服务与单体架构区别 3.3 微服务与SOA区别 4. 微服务本质 5. 什么样的项目适合微服务 6. 微服务折分与设计 6.1 微服务设计原则 7. 微服务…

linux gcc + openocd + stlink + cubeMX + cortex Debug

文章目录 运行环境&#xff1a;1.1 gcc1)下载并解压gcc2)环境配置 2.1 openocd1)下载并解压openocd2)环境配置&#xff08;没有权限就加sudo&#xff09; 3.1 stlink1)下载并双击安装stlink 4.1 cubeMX1)下载并解压cubeMX2)生成makefile工程 5.1 cortex Debug1)setting设置2)la…

冷链物流运转 3D 可视化监控,助力大数据实时监控

智慧物流是以信息化为依托并广泛应用物联网、人工智能、大数据、云计算等技术工具&#xff0c;在物流价值链上的 6 项基本环节&#xff08;运输、仓储、包装、装卸搬运、流通加工、配送&#xff09;实现系统感知和数据采集的现代综合智能型物流系统。随着冷链信息化、数字化发展…

史上最全! 瑞芯微RK3568核心板评估板资源分享!

▎瑞芯微RK3568芯片 高性能处理器&#xff1a;采用四核A55架构CPU&#xff0c;G52 GPU&#xff1b;内置NPU&#xff0c;可提供1T算力 高可靠性设计&#xff1a;支持DDR及CPU Cache全链路ECC 内置自研ISP图像处理器&#xff1a;8M30fps处理能力&#xff0c;强大的HDR功能&#…

Springboot Netty 实现自定义协议

Netty是由JBOSS提供的一个java开源框架&#xff0c;现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具&#xff0c;用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说&#xff0c;Netty 是一个基于NIO的客户、服务器端的编程框架&…

《编程思维与实践》1039.字符组合

《编程思维与实践》1039.字符组合 题目 思路 先将字符串去重排序(保证每个组合中的字符按字典序),然后枚举出所有组合的情形,最后再进行字典序排序即可. 其中字符串的去重排序可以利用ASCII码值进行桶排序,关键在于如何枚举所有组合的情形. 每个位置有两种可能(选或不选),但至…

MongoDB 聚合管道的输出结果到集合($out)及合并结果到集合($merge)

上一篇文章&#xff0c;我们介绍了使用聚合管道完成文档之间的关联查询、以及如果将两个管道中的文档进行合并&#xff0c;如果需要进一步了解可以参考&#xff1a;MongoDB 聚合管道的文档关联查询($lookup)及管道合并($unionWith)https://blog.csdn.net/m1729339749/article/d…

ES索引管理

ES官方博客&#xff1a;https://elasticstack.blog.csdn.net/?typeblog 一、rolloverAPI https://elasticstack.blog.csdn.net/article/details/102728987 1.1 rollover命令 POST /log_alias/_rollover { "conditions":{ "max_age":"…

Node 09 MongoDB的使用

MongoDB 简介 Mongodb 是什么 MongoDB 是一个基于分布式文件存储的数据库&#xff0c;官方地址 https://www.mongodb.com/ 数据库是什么 数据库&#xff08;DataBase&#xff09;是按照数据结构来组织、存储和管理数据的 应用程序 数据库的作用 数据库的主要作用就是 管理…

jsp家庭农场投入品信息管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 jsp家庭农场投入品信息管理系统是一套完善的java web信息管理系统 serlvet dao bean 开发&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发…

如何理解PCB布线3W规则

我们平时在PCB布线的时候&#xff0c;对于比较重要的信号都要做特殊处理&#xff0c;比如包地或者时“3W”&#xff0c;所谓3w指的是线与线之间的间距要满足三倍的线宽&#xff0c;那么我们怎么理解这个3W原则呢&#xff0c;他是如何降低信号之间的串扰的呢&#xff1f; 我们要…

连网介质及设备详解

文章目录 一、网卡1. 有线网卡2. 无线网卡3. 光纤网卡 二、网线1. 双绞线2. 光缆 三、交换机1. 什么是交换机2. 交换机分类 一、网卡 网卡分为三类&#xff1a;有线网卡、无线网卡、光纤网卡 1. 有线网卡 多数台式计算机自带&#xff0c;采用 RJ-45 制式接口 通过双绞线传输…