Distributed 原理解析
文章目录
- Distributed 原理解析
- 1 定义形式
- 2. 分片写入流程
- 2.1 分片规则
- 2.1.1 分片权重
- 2.1.2 slot
- 2.1.3 选择函数
- 2.2 数据写入核心流程
- 2.3 副本复制的核心流程
- 2.4 分布式查询流程
Distributed表引擎是分布式表的代名词,不存储
任何数据,只是作为代理,能够自动路由到集群中的各个节点,所以其需要和其他的表引擎一起工作。
一张分片表由两部分组成:
- 本地表:通常用
_local
结尾,主要承载数据。 - 分布式表:通常用
_all
结尾,其与本地表形成一对多的映射关系,通过分布式表可以操作多张本地表。
1 定义形式
一张Distributed表引擎的定义形式如下:
ENGINE = Distributed(cluster, database, table, [, sharding_key])
其中参数的含义如下:
- cluster:集群名称,与配置中的自定义名称对应。
- database和table:对应的数据库与数据表的名称
- sharding_key:分片键,可以通过这个值将数据分布到各个host节点的本地表。
对于Distributed表来说,其建表语句如下:
CREATE TABLE test_all ON CLUSTER sharding_simple {
id UINT64
}ENGINE = Distributed(sharding_simple, default, test_local, rand())
这里的部分集群名称,沿用之前的blog
上面建表语句的语义可以理解为:代理本地表default.test_local
,他们分布在集群sharding_simple
的各个shard
,数据写入时会根据rand()
随机函数取值来决定写入哪一个分片。
这里先创建Distributed表在创建本地表。
注意:ON CLUSTER sharding_simple
这个语义是在每一个分片节点上面创建一个Distributed
表。【不是必须的
接着创建本地表,使用分布式DDL语句可以迅速创建各个节点的本地表:
CREATE TABLE test_local ON CLUSTER sharding_simple (
id UINT64
)ENGINE = MergeTree()
ORDER BY id
PARTITION BY id
这里对该表的操作注意事项进行概括:
- 如果要彻底删除一张分布式表,那么Distributed和本地表都要删干净!
- 不支持任何的MUTATION查询,包括ALTER、DELETE、ALTER UPDATE
2. 分片写入流程
2.1 分片规则
2.1.1 分片权重
在之前可以看到ENGINE = Distributed(sharding_simple, default, test_local, rand())
中的rand()
。这个值意味着分布式表可以通过这个值映射到不同的本地表。这里需要引入分片权重的概念。
<!-- 1分片 1副本 -->
<sharding_simple> <!-- 自定义集群名字 -->
<shard> <!-- 分片 -->
...
<weight>10</weight> <!-- 分片权重 -->
</shard>
<!-- 分割 -->
<shard> <!-- 分片 -->
...
<weight>20</weight>
</shard>
</sharding_simple>
如果分片权重越大,那么其被写入的数据也会越多。
2.1.2 slot
slot的概念可以理解成一个个坑。slot的总和是所有分片的权重之和。如上面的配置,slot的数量等于30。slot按照权重元素的取值范围,与对应的分片形成映射关系。如果slot在[0,10)
之间则写入第一个分片;如果slot值落在[10,20]
之间则放入第二个分片。
2.1.3 选择函数
选择函数主要用于判断待写入数据应该被写入什么分片。
- 写出slot取值,计算公式如下:
- 基于slot值找到对应的数据分片
整个流程演示,这边使用表格的方式进行演示。
数据插入 | 公式值 | slot | shard |
(10) | 10 % 30 | 10 | Shard2 |
(30) | 30 % 30 | 0 | Shard1 |
(201) | 200 % 30 | 21 | Shard2 |
(50) | 55 % 30 | 20 | Shard2 |
2.2 数据写入核心流程
流程:
- 向第一个分片节点写入本地分片数据
- 第一个分片建立远端连接,准备发送远端分片数据
- 第一个分片向远端分片发送数据
- 第二个分片接受并写入本地
- 由第一个分片确认完成写入
2.3 副本复制的核心流程
这个部分根据建表的MergeTree类型,分成两种:
-
ReplicatedMergeTree
:之前就说过,这种引擎使用了zookeeper
的能力来实现副本之间的同步。那么可以想到,Distributed表即使向每一个分片中的一个副本写入数据,分片中的每个副本都可以有完整的数据! -
MergeTree
:这个也是一种方式,由于没有上述的特性,Distributed表写入时需要照顾到所有副本!这个就会出现写入瓶颈。
我们这边换个思路,既然使用了MergeTree来做分布式多机clickhouse,那我们为什么要用副本呢?
考虑使用raid5集群和高性能服务器不就阔以缓和了。【手动滑稽
还有一种考虑,那就是提高服务器成本,搞个单机的。
实际业务应用效果貌似还不错。