对于默认的分布式表的配置,每个分片只有一份,这种多分片单副本集群,挂掉一个节点的话查询分布式表会报错。为了解决这个问题的话可以使用ClickHouse高可用集群,对于每个分片具有2个或2个以上的副本,当某个节点挂掉时,该节点分片由其他节点的副本代替工作,这就避免了单点故障的问题。下面测试节点分别为:ambari01,ambari02,ambari03,ambari04
说明:下面的测试都是以internal_replication=true进行的。internal_replication参数,为true代表了只写入shard内的一台,与ZooKeeper配合进行复制;为false代表了写入shard内所有的replica,与分布式表配合进行复制。使用写分布式表的缺点:①使用写分布式表进行复制,则可能出现多写一边成功一边失败的情况,数据的一致性不可控,②在一台服务器宕机一阵子以后,再恢复过来则这个时间段里面的数据不能自动恢复从另外的replica恢复过来。
配置文件配置如下,由4个节点每个节点作为一个分片:
true
ambari01
admin
admin
9000
true
ambari02
admin
admin
9000
true
ambari03
admin
admin
9000
true
ambari04
admin
admin
9000
(1)在每个节点创建havail库,并使用这个库
create database havail;
use havail;
(2)在每个节点创建一个avail表,表引擎为MergeTree ,再创建一个分布式表avail_all,表引擎为Distributed
CREATE TABLE avail (Name String,StartDate Date,Year UInt16) ENGINE = MergeTree(StartDate,(Year, StartDate),8192);
CREATE TABLE avail_all (Name String,StartDate Date,Year UInt16) ENGINE= Distributed(ck_cluster, havail, avail, rand());
(3)在ambari01往avail_all表中插入一条数据并查询
insert into avail_all (Name,StartDate,Year)values('zs','2019-01-01',2019);
select * from avail_all;
(4)在每个节点上查询avail表,看写入分布表的数据存储在哪个节点的avail表上,插入分布表的数据只会存储在一个avail表上
select * from avail;
(5)发现数据存储在ambari02节点,手动停止ambari02的ClickHouse进程。在ambari01节点执行查询语句,报错
配置文件配置如下,有4个节点2个shard,ambari01和ambari02为一个shard,ambari03和ambari04为2个shard:
true
ambari01
admin
admin
9000
ambari02
admin
admin
9000
true
ambari03
admin
admin
9000
ambari04
admin
admin
9000
(1)同步上面配置到每个节点,并重启每个节点的ClickHouse
(2)使用前面建好的havail库
use havail;
(3)在每个节点创建一个havail表,表引擎为MergeTree ,再创建一个分布式表havail_all,表引擎为Distributed
CREATE TABLE havail (Name String,StartDate Date,Year UInt16) ENGINE = MergeTree(StartDate,(Year, StartDate),8192);
CREATE TABLE havail_all (Name String,StartDate Date,Year UInt16) ENGINE= Distributed(ck_cluster, havail, havail, rand());
(4)在ambari01往havail_all表中插入1条数据并查询
insert into havail_all (Name,StartDate,Year)values('zs','2019-01-01',2019);
select * from havail_all;
(5)在每个节点上查询havail表,看写入分布表的数据存储在哪个节点的havail表上
select * from havail;
可以发现虽然做了副本,但是MergeTree 引擎的表并不会自动复制数据,所有数据还是只在一个节点上
(6)发现数据存储在ambari01节点,手动停止ambari01的ClickHouse进程。在ambari02节点执行查询语句,发现不报错,但是没有数据。
高可用加复制表是使用ReplicatedMergeTree 引擎+ Distributed引擎,作为集群结构的引擎。
CREATE TABLE table_name
(
EventDate DateTime,
CounterID UInt32,
UserID UInt32
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}', EventDate, intHash32(UserID), (CounterID, EventDate, intHash32(UserID), EventTime), 8192)
官网已经不推荐上述建表语句,但是重点是测试,所以还是使用如上建表语句,官网推荐的推荐如下:
CREATE TABLE table_name
(
EventDate DateTime,
CounterID UInt32,
UserID UInt32,
ver UInt16
) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}', ver)
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
SAMPLE BY intHash32(UserID)
配置文件配置如下,有4个节点2个shard,ambari01和ambari02为一个shard,ambari03和ambari04为2个shard:
true
ambari01
admin
admin
9000
ambari02
admin
admin
9000
true
ambari03
admin
admin
9000
ambari04
admin
admin
9000
(1)同步上面配置到每个节点,并重启每个节点的ClickHouse
(2)使用前面建好的havail库
use havail;
(3)在每个节点创建一个havail表,表引擎为MergeTree ,再创建一个分布式表havail_all,表引擎为Distributed
CREATE TABLE havail_re (Name String,StartDate Date,Year UInt16) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-01/havail_re','havail_re-01-1',StartDate,(Year, StartDate),8192); #分片1的第1个副本,ambari01执行
CREATE TABLE havail_re (Name String,StartDate Date,Year UInt16) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-01/havail_re','havail_re-01-2',StartDate,(Year, StartDate),8192); #分片1的第2个副本,ambari03执行
CREATE TABLE havail_re (Name String,StartDate Date,Year UInt16) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-02/havail_re','havail_re-02-1',StartDate,(Year, StartDate),8192); #分片2的第1个副本,ambari03执行
CREATE TABLE havail_re (Name String,StartDate Date,Year UInt16) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-02/havail_re','havail_re-02-2',StartDate,(Year, StartDate),8192); #分片2的第2个副本,ambari04执行
CREATE TABLE havail_re_all (Name String,StartDate Date,Year UInt16) ENGINE= Distributed(ck_cluster, havail, havail_re, rand());
注意:ReplicatedMergeTree的参数:第一个:‘zk路径,如果要相互复制,这里必须一样’, 第二哥:‘副本名称, 必须不一样’, 剩下的就是分区和主键,以及索引粒度
(4)在ambari01往havail_re_all分布式表中插入1条数据并查询
insert into havail_re_all (Name,StartDate,Year)values('zs','2019-01-01',2019);
select * from havail_re_all;
(5)在每个节点上查询havail_re表,看写入分布表的数据存储在哪个节点的havail_re表上
select * from havail_re;
可以发现我们在ambari01和ambari02这两个节点的本地表havail_re都可以查到数据,说明插入数据到分布表能复制。
(6)在ambari03往havail_re本地表中插入1条数据并查询
insert into havail_re (Name,StartDate,Year)values('zs','2020-02-02',2020);
(7)查看分布式表havail_re_all可以看到前面插入的2条记录都能查询
(8)查看ambari03和ambari04的本地表是否相互复制了
说明往本地表插入数据也会进行复制
(9)停掉ambari03的ClickHouse进程查看分布表havail_re_all是否能正常工作
在ambari01上查看分布表havail_re_all能正常查询,并且不会丢数据
(1)没有配置副本,非复制表,每个节点为一个shard的情况:数据只被插入到一个本地表中,但没有任何机制可以将它转移到另一个表中。当一个节点挂了之后查询分布表会报错
(2)配置副本,非复制表的情况:据只被插入到一个本地表中,但没有任何机制可以将它转移到另一个表中。当一个节点挂了之后查询分布表不会报错,但是挂了的节点的数据会丢失
(3)配置副本,复制表的情况:插入到分布式表中的数据仅插入到其中一个本地表中,但通过复制机制传输到另一个节点的表中,因此两个本地表上的数据保持同步。推荐使用这种配置。