副本虽然可以提高数据的可用性,但每台服务器必须容纳全量数据,没有支持数据的横向扩容。要解决数据水平切分问题,需要引入分片的概念,通过分片把一份完整的数据进行切分,不同的分片分布到不同的节点上,再通过Distributed
分布表引擎把数据拼接起来使用。
分布引擎本身不存储数据,而是通过分布式逻辑进行不同分片的分布式数据的写入、分发和路由。
因为ClickHouse的集群是表级别的,所以实际企业大部分做了高可用,但没有分片,以避免降低查询性能和操作集群的复杂度。
以3分片,每个分片2个副本,共6个结点为例:
绿色表示打开分片内部复制的情况,黄色表示关闭分片内部复制的情况。打开分片内部复制时,客户端向分布式表distribute hdp1
发送写命令,distribute hdp1
只会向三个切片的一个副本写入数据,上图中即为hdp1 s1r1
、hdp3 s2r3
和hdp5 s3r5
,而后每个副本向该切片的另一个副本再写入数据,即hdp1 s1r1
向hdp2 s1r2
、hdp3 s2r3
向hdp4 s2r4
、hdp5 s3r5
向hdp6 s3r6
写入数据。关闭分片内部复制时,distribute hdp1
就得自己向所有副本写入数据。
以3分片,每个分片2个副本,共6个结点为例:
当客户端向分布表发送读命令时,分布表向每个分片预读取数据,并计算错误数errors_count
,优先选择分片内错误数小的副本数据,如果存在多个拥有最小错误数的副本,则通过随机、顺序、第一顺位优先或host
名称近似四种方式之一选择其中一个副本的数据,最后将每个分片的数据进行拼接,作为最终的读取结果返回给客户端。
进入/etc/clickhouse-server
目录
[root@scentos szc]# cd /etc/clickhouse-server
[root@scentos clickhouse-server]#
修改config.xml
文件
[root@scentos clickhouse-server]# vim config.xml
将
标签修改成如下内容:
<remote_servers>
<szc_cluster>
<shard>
<internal_replication>trueinternal_replication>
<replica>
<host>scentoshost>
<port>9000port>
replica>
shard>
szc_cluster>
remote_servers>
为集群名称,
为分片,
表示是否打开分片内部复制,
为分片副本,分片内部可以配置多个副本,集群内部可以配置多个分片,但每个分片的副本数不用一样。
然后打开
标签的注释,配置当前机器的分片id和副本id:
<macros>
<shard>01shard>
<replica>rep_01_1replica>
macros>
最后重启ClickHouse:
[root@scentos clickhouse-server]# systemctl restart clickhouse-server
首先通过副本合并树创建数据表:
create table st_order_mt on cluster szc_cluster (
id UInt32,
sku_id String,
total_amount Decimal(16,2),
create_time Datetime
) engine
=ReplicatedMergeTree('/clickhouse/tables/01/st_order_mt','rep_01_1')
partition by toYYYYMMDD(create_time)
primary key (id)
order by (id,sku_id);
szc_cluster
为使用的集群名称,ReplicatedMergeTree('/clickhouse/tables/01/st_order_mt','rep_01_1')
中的参数含义如下:
/clickhouse/tables/01/st_order_mt
:/clickhouse/tables
固定,01
为建表的分片id,st_order_mt
为表名;rep_01_1
为建表的副本ID在某个副本建表后,所有分片的所有副本都会拥有这张表。
执行结果如下图所示:
然后创建分布式表:
create table st_order_mt_all2 on cluster szc_cluster
(
id UInt32,
sku_id String,
total_amount Decimal(16,2),
create_time Datetime
)engine = Distributed(szc_cluster,default, st_order_mt,hiveHash(sku_id));
szc_cluster
为集群名称,Distributed(szc_cluster,default, st_order_mt,hiveHash(sku_id)
中参数含义如下:
szc_cluster
表示使用的集群名称;default
表示使用的数据库名称;st_order_mt
表示该分布式表控制的表名称;hiveHash(sku_id)
表示分片方法,即通过计算sku_id
的哈希值来确定数据所属的分片。执行结果如下图所示:
然后我们可以通过分布式表st_order_mt_all2插入数据:
insert into st_order_mt_all values
(201,'sku_001',1000.00,'2020-06-01 12:00:00') ,
(202,'sku_002',2000.00,'2020-06-01 12:00:00'),
(203,'sku_004',2500.00,'2020-06-01 12:00:00'),
(204,'sku_002',2000.00,'2020-06-01 12:00:00'),
(205,'sku_003',600.00,'2020-06-02 12:00:00');
也可以通过分布式表st_order_mt_all2
查询数据:
数据表和分布式表存在于集群中所有结点上,如果我们读写数据表,就只能读写结点所在分片的数据,不能读写跨分片结点的数据,因此集群模式下,我们必须通过分布式表进行全局的跨分片读写。