环境介绍

Clickhouse高可用集群采用ReplicatedMergeTree + Distributed方案,2分片2副本,共4个节点

注意:本文档不展示zookeeper集群的安装过程,请自行查找zk集群安装文档。生产环境建议Zookeeper独立服务器部署,Clickhouse集群对Zookeeper依赖较高。

名称 版本
操作系统 Centos7.9
ClickHouse版本(RPM) 21.9.7.2
Zookeeper集群 3.4.5
Node01 192.168.99.28
Node02 192.168.99.29
Node03 192.168.99.30
Node04 192.168.99.21

操作系统准备工作

准备工作四台主机都需要操作。

我这里准备clickhouse单独数据盘挂载,如果数据不单独存储可以省略此步。

1
2
3
4
5
6
7
8
9
10
pvcreate /dev/sdb
vgcreate data /dev/sdb
lvcreate --name data_01 -l 100%FREE data
mkfs.ext4 /dev/mapper/data-data_01
mkdir -p /data/clickhouse

cat >> /etc/fstab<<EOF
/dev/mapper/data-data_01 /data ext4 defaults,noatime 0
EOF
mount -a

修改系统文件安全上限配置安装依赖

1
2
3
4
5
6
7
$ vim /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072

$ yum install -y libtool *unixODBC*

关闭防火墙和Selinux

1
2
3
4
5
6
7
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

#关闭selinux
sed -i 's/=enforcing/=disabled/g' /etc/selinux/config
setenforce 0

开始离线安装

下载并安装软件包

https://repo.yandex.ru/clickhouse/rpm/stable/x86_64,下载离线rpm安装包,clickhouse-client*clickhouse-common-static*clickhouse-common-static-dbg*
clickhouse-server*这四个安装包的版本要一致

我这里安装的是21.9.7.2版本,下面是下载地址这里可以先下载软件包到一台主机,然后通过scp的方式传送到另外三台主机。

1
2
3
4
5
6
$ cd /usr/local/src
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-client-21.9.7.2-2.noarch.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-common-static-21.9.7.2-2.x86_64.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-common-static-dbg-21.9.7.2-2.x86_64.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-server-21.9.7.2-2.noarch.rpm
wget https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/clickhouse-test-21.9.7.2-2.noarch.rpm

四台主机都执行下面命令安装clickhouse的rpm包到主机。

1
2
3
4
5
6
# 安装
$ yum install -y ./*.rpm

# 修改挂载数据目录的属主和属组
mkdir -p /data/clickhouse
chown -R clickhouse:clickhouse /data/clickhouse/ && chmod 700 /data/clickhouse/

修改配置文件

修改四台主机的clickhouse主配置文件config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ vim /etc/clickhouse-server/config.xml
<!--注意,此处显示修改后的配置,其他可自行配置-->
<!--我主机的9000端口占用了,这里改成29000-->
<tcp_port>29000</tcp_port>
<!--副本复制同步数据时用的当前节点ip,如果不设置默认是主机名,除非你设置主机名解析,不然会造成副本节点无法同步数据-->
<interserver_http_host>192.168.99.28</interserver_http_host>
<!--监听主机的所有地址-->
<listen_host>0.0.0.0</listen_host>
<!--支持的最大连接数-->
<max_connections>4096</max_connections>
<!--下面是修改默认的data目录到自定义的/data目录-->
<path>/data/clickhouse/</path>
<tmp_path>/data/clickhouse/tmp/</tmp_path>
<format_schema_path>/data/clickhouse/format_schemas/</format_schema_path>
<user_files_path>/data/clickhouse/user_files/</user_files_path>
<path>/data/clickhouse/access/</path>
<!--...-->
<!--包含的集群配置文件,后面我们集群的配置都写到这个文件中-->
<include_from>/etc/clickhouse-server/config.d/metrika.xml</include_from>
<!--...-->

四个节点新建都需要的配置文件/etc/clickhouse-server/config.d/metrika.xml,一段不同的配置在下面列举,相同的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
$ vim /etc/clickhouse-server/config.d/metrika.xml
<yandex>
<!--ck集群节点-->
<remote_servers>
<!-- 集群名称,你可以自定义 -->
<test_cdh_ck_cluster>
<!--分片1-->
<shard>
<!-- 分片的权重 -->
<weight>1</weight>

<!-- 这个参数是控制写入数据到分布式表时,分布式表会控制这个写入是否的写入到所有副本中。与复制表的同步是不一样的。为什么<2>中要设置为true,这就是为了避免和复制表的同步复制机制出现冲突,导致数据重复或者不一致。 -->
<internal_replication>true</internal_replication>
<!-- 分片1的第一个副本 -->
<replica>
<host>192.168.99.28</host>
<port>29000</port>
<user>default</user>
<password></password>
<compression>true</compression>
</replica>
<!-- 分片1的第二个副本 -->
<replica>
<host>192.168.99.30</host>
<port>29000</port>
<user>default</user>
<password></password>
<compression>true</compression>
</replica>
</shard>
<!--分片2-->
<shard>
<weight>1</weight>
<internal_replication>true</internal_replication>
<!-- 分片2的第一个副本 -->
<replica>
<host>192.168.99.29</host>
<port>29000</port>
<user>default</user>
<password></password>
<compression>true</compression>
</replica>
<!-- 分片2的第二个副本 -->
<replica>
<host>192.168.99.21</host>
<port>29000</port>
<user>default</user>
<password></password>
<compression>true</compression>
</replica>
</shard>
</test_cdh_ck_cluster>
</remote_servers>

<!--你的zookeeper集群相关配置-->
<zookeeper>
<node index="1">
<host>192.168.99.28</host>
<port>2181</port>
</node>
<node index="2">
<host>192.168.99.29</host>
<port>2181</port>
</node>
<node index="3">
<host>192.168.99.30</host>
<port>2181</port>
</node>
</zookeeper>

<!-- 网络配置,监听所有地址 -->
<networks>
<ip>::/0</ip>
</networks>

<!--压缩相关配置-->
<clickhouse_compression>
<case>
<min_part_size>10000000000</min_part_size>
<min_part_size_ratio>0.01</min_part_size_ratio>
<method>lz4</method> <!--压缩算法lz4压缩比zstd快, 更占磁盘-->
</case>
</clickhouse_compression>

<!-- 各节点以下配置段不同,注意修改 -->
<macros>
<!-- 分片的编号,同一个分片的主和副本副本这里的编号一定要相同 -->
<shard>01</shard>
<!--当前节点主机名: 我这里写的是主机名 分片名 副本名-->
<replica>ch28-01-01</replica>
</macros>

</yandex>

Node01-99.28节点不同的集群配置字段如下

1
2
3
4
5
6
<macros>
<!-- 分片的编号,同一个分片的主和副本副本这里的编号一定要相同 -->
<shard>01</shard>
<!--当前节点主机名: 我这里写的是主机名 分片名 副本名-->
<replica>ch28-01-01</replica>
</macros>

Node02-99.29节点不同的集群配置字段如下

1
2
3
4
<macros>
<shard>02</shard>
<replica>ch29-02-01</replica> <!--当前节点主机名: 我这里写的是主机名 分片名 副本名-->
</macros>

Node03-99.30节点不同的集群配置字段如下

1
2
3
4
<macros>
<shard>01</shard>
<replica>ch30-01-02</replica> <!--当前节点主机名: 我这里写的是主机名 分片名 副本名-->
</macros>

Node04-99.21节点不同的集群配置字段如下

1
2
3
4
<macros>
<shard>02</shard>
<replica>ch21-02-02</replica> <!--当前节点主机名: 我这里写的是主机名 分片名 副本名-->
</macros>

修改所有节点的目录的属组,因为刚刚新建的用户可能是root,我们要改成属组和属主是clickhouse

1
$ chown -R clickhouse:clickhouse /etc/clickhouse-server/

启动服务

完成后现在就可以启动各节点的clickhouse服务了。

1
2
3
4
5
6
7
# 所有节点执行启动命令,不要用systemctl启动,可能有问题
$ /etc/init.d/clickhouse-server start

# 查看端口是否起来
$ ss -tnl |egrep '29000|8123'
LISTEN 0 64 *:29000 *:*
LISTEN 0 64 *:8123 *:*

如果启动有问题就可以

连接集群并建库验证

任何一台机器使用clickhouse-client命令行工具连接到服务

1
2
3
4
5
6
7
8
# 默认是9000端口,因为我们改了所以这里要指定,默认用户名是default密码是空,我们没有改所以直接就连接了。
$ clickhouse-client --port 29000
clickhouse-client --port 29000
ClickHouse client version 21.9.7.2 (official build).
Connecting to localhost:29000 as user default.
Connected to ClickHouse server version 21.9.7 revision 54449.

k8s-master21 :)

查看集群信息

1
2
3
4
5
6
7
8
9
10
11
12
:) select cluster,shard_num,replica_num,shard_weight,host_name,port,user from system.clusters;

┌─cluster─────────┬─shard_num─┬─replica_num─┬─shard_weight─┬─host_name─────┬──port─┬─user────┐
│ test_cdh_ck_cluster │ 111192.168.99.2829000default
│ test_cdh_ck_cluster │ 121192.168.99.3029000default
│ test_cdh_ck_cluster │ 211192.168.99.2929000default
│ test_cdh_ck_cluster │ 221192.168.99.2129000default
└─────────────────┴───────────┴─────────────┴──────────────┴───────────────┴───────┴─────────┘
# 可以看到如下信息
# test_cdh_ck_cluster为我们的集群名称
# 分片1的第一个副本是99.28,第二个副本是99.30
# 分片2的第一个副本是99.29,第二个副本是99.21

创建数据库因为有on cluster test_cdh_ck_cluster语句字段,所有会自动在所有节点执行。

1
create database testdb on cluster test_cdh_ck_cluster;

创建本地表,如果去掉ON CLUSTER test_cdh_ck_cluster语句字段则需要每个节点都要创建。

1
create table testdb.table_test ON CLUSTER test_cdh_ck_cluster ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/tables/test_cdh_ck_cluster/{shard}/table_test','{replica}',insert_time, (label_id, insert_time), 8192);

ReplicatedMergeTree 引擎用法: ENGINE = ReplicatedMergeTree('zk_path', 'replica_name')

zk_path 用于指定在 zk 中创建数据表的路径,一般 zk_path 建议配置成如下形式:

  • /clickhouse/tables/{cluster}/{shard}/{table_name},{replica}
  • {cluster} 表示集群名,替换成实际的集群名
  • {shard} 表示分片编号,ch中已定义宏变量,会自动读取本节点的值
  • {table_name} 表示数据表的名称,替换成实际的表名
  • {replica} 表示副本编号,ch中已定义宏变量,会自动读取本节点的值

4个节点需要手动去创建分布式表

1
CREATE TABLE table_test_all AS table_test ENGINE = Distributed(test_cdh_ck_cluster, testdb, table_test, rand());

也可以用下面命令直接在集群中创建

1
2
# 需要注意的是这俩不能用as字段了,需要指定字段
CREATE TABLE table_test_all ON CLUSTER test_cdh_ck_cluster ( label_id UInt32, label_name String, insert_time Date) ENGINE = Distributed(test_cdh_ck_cluster, testdb, table_test, rand());

说明:

  • test_cdh_ck_cluster:集群名称
  • table_test_all:分布式表名称
  • testdb:数据库名称
  • table_test:本地表名称
  • rand():随机分配

我们往分布式表插入8条数据

1
2
3
4
5
6
7
8
insert into table_test_all values (1,'111','2021-09-11');
insert into table_test_all values (2,'222','2021-10-22');
insert into table_test_all values (3,'333','2021-10-33');
insert into table_test_all values (4,'444','2021-10-44');
insert into table_test_all values (5,'555','2021-10-55');
insert into table_test_all values (6,'666','2021-10-66');
insert into table_test_all values (7,'777','2021-10-77');
insert into table_test_all values (8,'888','2021-10-88');

下面分别登录各节点查看分布式表的数据都是8条

Node01-99.28节点

1
2
3
4
:) select count(*) from table_test_all;
┌─count()─┐
8
└─────────┘

Node02-99.29节点

1
2
3
4
:) select count(*) from table_test_all;
┌─count()─┐
8
└─────────┘

Node03-99.30节点

1
2
3
4
:) select count(*) from table_test_all;
┌─count()─┐
8
└─────────┘

Node04-99.21节点

1
2
3
4
:) select count(*) from table_test_all;
┌─count()─┐
8
└─────────┘

查看各节点的本地表及副本分片的数据。

node01和node03都是分片1的主和副本分片,这里本地表数据肯定是一样的,只是查询出来顺序不一样而已。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# node01-99.28
:) select * from table_test;
┌─label_id─┬─label_name─┬─insert_time─┐
11112021-09-11
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
88881970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
66661970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
33331970-01-01
└──────────┴────────────┴─────────────┘

# node03-99.30
:) select * from table_test;
┌─label_id─┬─label_name─┬─insert_time─┐
66661970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
33331970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
88881970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
11112021-09-11
└──────────┴────────────┴─────────────┘

node02和node04都是分片2的主和副本分片,这里本地表数据肯定是一样的,只是查询出来顺序不一样而已。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# node02-99.29
:) select * from table_test;
┌─label_id─┬─label_name─┬─insert_time─┐
22222021-10-22
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
77771970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
55551970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
44441970-01-01
└──────────┴────────────┴─────────────┘

# node04-99.21
:) select * from table_test;
┌─label_id─┬─label_name─┬─insert_time─┐
77771970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
22222021-10-22
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
55551970-01-01
└──────────┴────────────┴─────────────┘
┌─label_id─┬─label_name─┬─insert_time─┐
44441970-01-01
└──────────┴────────────┴─────────────┘

至此集群就安装成功了。

安装成功后的管理信息

服务启停管理命令

1
2
3
4
$ /etc/init.d/clickhouse-server start
$ /etc/init.d/clickhouse-server restart
$ /etc/init.d/clickhouse-server stop
$ /etc/init.d/clickhouse-server status

终端clickhouse-client命令连接

1
$ clickhouse-client --port 29000

第三方Gui工具连接

1
2
连接地址:192.168.99.28:8123
账号密码:default/密码为空

数据目录

1
/data/clickhouse

日志目录

1
/var/log/clickhouse-server/