作者简介
马听,多年 DBA 实战经验,对 MySQL、 Redis、ClickHouse 等数据库有一定了解,专栏《一线数据库工程师带你深入理解 MySQL》、《Redis 运维实战》作者。
在海量数据的场景下,单节点的 CH 可能不能满足我们的需求了,因此可以考虑使用 CH 集群,从而解决单节点存储和查询的瓶颈。
这一节就来聊聊 CH 集群的部署。
实验环境
- CentOS 7.4
- ClickHouse 20.7.2.30
首先来看下本节内容大致的架构:
如上图,整个集群一共 4 个节点,分为两个分片,每个分片一个副本。除了在每个节点创建 ReplicatedMergeTree 表,还会创建 Distributed 引擎的总表(建表方式在本文后面会讲解),各个节点上的本地表代理,写入、查询、分发等操作都经过分布式总表路由。
1 安装 zk
由于 ReplicatedMergeTree 引擎依赖 zk,有数据写入或者修改时,就借助 zk 的分布式协同能力,实现多个副本之间的同步。因此需要安装 zk。
ZooKeeper 安装参考:https://zookeeper.apache.org/doc/r3.4.14/zookeeperStarted.html
2 安装 ClickHouse
4 台机器都先安装好单机版 ClickHouse,ClickHouse 单机版安装参考:https://clickhouse.tech/docs/zh/getting-started/install/。
编辑配置文件
代码语言:javascript复制vim /etc/clickhouse-server/config.xml
去掉下面这行的注释
代码语言:javascript复制<listen_host>::</listen_host>
3 增加集群配置文件
代码语言:javascript复制vim /etc/clickhouse-server/config.d/metrika.xml
加入如下内容:
代码语言:javascript复制<?xml version="1.0"?>
<yandex>
<zookeeper-servers>
<node index="1">
<host>192.168.150.232</host>
<port>2181</port>
</node>
</zookeeper-servers>
<clickhouse_remote_servers>
<!-- 2分片1副本 -->
<cluster_test>
<!-- 数据分片1 -->
<shard>
<weight>1</weight>
<!-- Optional. Whether to write data to just one of the replicas. Default: false (write data to all replicas). -->
<internal_replication>true</internal_replication>
<replica>
<host>192.168.150.232</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.150.253</host>
<port>9000</port>
</replica>
</shard>
<!-- 数据分片2 -->
<shard>
<weight>1</weight>
<internal_replication>true</internal_replication>
<replica>
<host>192.168.150.123</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.21.126</host>
<port>9000</port>
</replica>
</shard>
</cluster_test>
</clickhouse_remote_servers>
<macros>
<cluster>cluster_test</cluster>
<shard>01</shard>
<replica>replica01</replica>
</macros>
</yandex>
注意修改 zk 以及各个节点的信息。
其中 192.168.150.232 和 192.168.150.253 为分片 01 的两个副本;192.168.150.123 和 192.168.21.126 为分片 02 的两个副本。
4 台机器除了下面这一段需要修改成对应的 shard 和 replica,其他都一样。
代码语言:javascript复制<macros>
<cluster>cluster_test</cluster>
<shard>01</shard>
<replica>replica01</replica>
</macros>
4 修改 ClickHouse 主配置文件
代码语言:javascript复制vim /etc/clickhouse-server/config.xml
增加
代码语言:javascript复制<include_from>/etc/clickhouse-server/config.d/metrika.xml</include_from>
<zookeeper incl="zookeeper-servers" optional="false" />
启动服务
代码语言:javascript复制/etc/init.d/clickhouse-server start
5 查看集群信息
随便选择一个节点,登录 ClickHouse
代码语言:javascript复制clickhouse-client
然后查看集群信息
代码语言:javascript复制select * from system.clusters;
6 创建本地表
先解释一下 ReplicatedMergeTree 引擎用法:
代码语言:javascript复制ENGINE = ReplicatedMergeTree('zk_path', 'replica_name')
zk_path 用于指定在 zk 中创建数据表的路径,一般 zk_path 建议配置成如下形式:
代码语言:javascript复制/clickhouse/{cluster}/{shard}/{table_name}
- {cluster} 表示集群名;
- {shard} 表示分片编号;
- {table_name} 表示数据表的名称。
replica_name 的定义,需要注意的是同一分片不同副本,需要定义不同的名称;
而 zk_path 的定义,需要注意的是同一分片不同副本,需要定义相同的路径。
上面两句话如果感觉有点绕,可以对比下面这 4 个节点的本地表建表语句,应该就可以理解啦。
在 192.168.150.232 上:
代码语言:javascript复制CREATE DATABASE likecolumn;
CREATE TABLE likecolumn.table_test ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/cluster_test/01/table_test','replica01',insert_time, (label_id, insert_time), 8192)
在 192.168.150.253 上:
代码语言:javascript复制CREATE DATABASE likecolumn;
CREATE TABLE likecolumn.table_test ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/cluster_test/01/table_test','replica02',insert_time, (label_id, insert_time), 8192)
在 192.168.150.123 上:
代码语言:javascript复制CREATE DATABASE likecolumn;
CREATE TABLE likecolumn.table_test ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/cluster_test/02/table_test','replica01',insert_time, (label_id, insert_time), 8192)
在 192.168.21.126 上:
代码语言:javascript复制CREATE DATABASE likecolumn;
CREATE TABLE likecolumn.table_test ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/cluster_test/02/table_test','replica02',insert_time, (label_id, insert_time), 8192)
7 创建分布式总表
任选一个集群内的节点创建分布式总表:
代码语言:javascript复制CREATE TABLE likecolumn.table_test_all AS likecolumn.table_test ENGINE = Distributed(cluster_test, likecolumn, table_test, rand())
这里解释一下 Distributed 引擎用法: ENGINE = Distributed(cluster, database, table, sharding_key)
- cluster:集群名
- database 和 table:库表名
- sharding_key:分片键,选填。
8 数据测试
在创建了分布式总表的节点写入数据:
代码语言:javascript复制insert into likecolumn.table_test_all values (1,'111','2020-11-17');
insert into likecolumn.table_test_all values (2,'111','2019-11-18');
insert into likecolumn.table_test_all values (3,'111','2020-11-19');
insert into likecolumn.table_test_all values (4,'111','2020-11-20');
查询总表数据
代码语言:javascript复制select * from likecolumn.table_test_all ;
查询各个分片本地表的数据。
代码语言:javascript复制select * from likecolumn.table_test ;
01 分片两个节点的数据如下:
02 分片两个节点的数据如下:
9 高可用测试
停掉 192.168.150.123 的 ClickHouse 服务:
代码语言:javascript复制/etc/init.d/clickhouse-server stop
发现整个集群仍然可以正常写入和查询: