clickhouse安装及集群搭建
# 简介
ClickHouse是一个面向列的数据库管理系统(DBMS),用于在线分析处理查询(OLAP)。
简单的说ClickHouse作为分析型数据库,三大特点:一是跑分快, 二是功能多 ,三是文艺范。
# 特性
- 真正面向列的DBMS、支持压缩
- 支持普通硬盘存储、支持多核并行处理
- 支持SQL、支持矢量引擎、支持实时数据更新
- 支持索引、支持在线查询
- 支持近似计算、支持数据辅助和数据完整性
# 应用场景
- 绝大多数请求都是用于读访问的,数据只是添加到数据库,没有必要修改
- 数据需要以大批量(大于1000行)进行更新,而不是单行更新;或者根本没有更新操作
- 读取数据时,会从数据库中提取出大量的行,但只用到一小部分列
- 表很“宽”,即表中包含大量的列
- 查询频率相对较低(通常每台服务器每秒查询数百次或更少)
- 对于简单查询,允许大约50毫秒的延迟
- 列的值是比较小的数值和短字符串(例如,每个URL只有60个字节)
- 在处理单个查询时需要高吞吐量(每台服务器每秒高达数十亿行)
- 不需要事务,数据一致性要求较低
- 每次查询中只会查询一个大表。除了一个大表,其余都是小表
- 查询结果显著小于数据源。即数据有过滤或聚合。返回结果不超过单个服务器内存大小
# 安装
# 单独命令安装
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://packages.clickhouse.com/rpm/clickhouse.repo
sudo yum install -y clickhouse-server clickhouse-client
#如果安装时出现warning: rpmts_HdrFromFdno: Header V4 RSA/SHA1 Signature, key ID e0c56bd4: NOKEY错误导致无法安装,需要在安装命令中添加—nogpgcheck来解决。
sudo yum install -y clickhouse-server clickhouse-client --nogpgcheck
sudo /etc/init.d/clickhouse-server start
clickhouse-client # or "clickhouse-client --password" if you set up a password.
2
3
4
5
6
7
8
9
# 提前离线下载包
yumdownloader --downloadonly clickhouse-server clickhouse-client clickhouse-common-static
root@host116[/var/www/html/files/ckman/clickhouse]# ls -lh
总用量 120K
-rw-r--r-- 1 root root 6511 6月 2 2018 clickhouse-client-1.1.54385-2.x86_64.rpm
-rw-r--r-- 1 root root 30955 2月 17 22:51 clickhouse-client-22.2.2.1-2.noarch.rpm
-rw-r--r-- 1 root root 223610019 2月 17 22:51 clickhouse-common-static-22.2.2.1-2.x86_64.rpm
-rw-r--r-- 1 root root 21437 6月 2 2018 clickhouse-server-1.1.54385-2.x86_64.rpm
-rw-r--r-- 1 root root 56238 2月 17 22:51 clickhouse-server-22.2.2.1-2.noarch.rpm
#离线安装只需要下面三个包
-rw-r--r-- 1 root root 30955 2月 17 22:51 clickhouse-client-22.2.2.1-2.noarch.rpm
-rw-r--r-- 1 root root 223610019 2月 17 22:51 clickhouse-common-static-22.2.2.1-2.x86_64.rpm
-rw-r--r-- 1 root root 56238 2月 17 22:51 clickhouse-server-22.2.2.1-2.noarch.rpm
rpm -ivh clickhouse*.rpm
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 卸载重装
卸载及删除安装文件
yum list installed | grep clickhouse
yum remove -y clickhouse-common-static
yum remove -y clickhouse-server-common
#yum remove -y clickhouse-common-static clickhouse-server-common clickhouse-server clickhouse-client
rm -rf /var/lib/clickhouse /ckdata1
rm -rf /etc/clickhouse-*
rm -rf /var/log/clickhouse-server
2
3
4
5
6
7
8
9
下载rpm包
https://packagecloud.io/app/Altinity/clickhouse/search?
安装
yum install -y clickhouse-common-static-18.12.17-1.el7.x86_64.rpm
yum install -y clickhouse-server-common-18.12.17-1.el7.x86_64.rpm
yum install -y clickhouse-server-18.12.17-1.el7.x86_64.rpm
yum install -y clickhouse-client-18.12.17-1.el7.x86_64.rpm
2
3
4
启动查询服务
#启动服务
service clickhouse-server start
#查询服务状态
service clickhouse-server status
#判断client端口是否被占用,默认为9000
netstat -tunlp|grep 9000
#占用则可以修改server的配置文件。开启访问权限 修改server的配置文件
<listen_host>::<listen_host>
<listen_host>::1<listen_host>
<listen_host>127.0.0.1<listen_host>
2
3
4
5
6
7
8
9
10
11
12
13
# 配置启动
# 配置相关
# 系统配置
clickhouse的server配置,在/etc/clickhouse-server/config.xml及user.xml;
- 前者是clickhouse 的系统配置,包括日志,服务部署ip,zk等配置。服务配置:config.xml
- 后者是当前节点服务的配置,包括用户名密码, 内存大小限制等。用户配置:users.xml
# config.xml
config.xml
文件是clickhouse
默认的配置文件,路径为/etc/clickhouse-server/config.xml
。
config.xml
中可以配置的内容有很多,下面节选一些比较重要的配置项来说明一下:
<?xml version="1.0"?>
<yandex>
<logger>
<!-- clickhouse日志相关的配置 -->
<level>trace</level>
<log>/var/log/clickhouse-server/clickhouse-server.log</log> <!--日志路径-->
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
<size>1000M</size>
<count>10</count>
</logger>
<http_port>8123</http_port> <!--http 客户端连接ck的端口-->
<tcp_port>9000</tcp_port> <!--tcp 客户端连接ck的端口 -->
<mysql_port>9004</mysql_port>
<listen_host>::</listen_host> <!--ip地址,配置成::可以被任意ipv4和ipv6的客户端连接, 需要注意的是,如果机器本身不支持ipv6,这样配置是无法启动clickhouse的,这时候可以改成0.0.0.0 -->
<path>/var/lib/clickhouse/</path> <!--ck存放数据库内容的路径-->
<user_files_path>/var/lib/clickhouse/user_files/</user_files_path> <!--File 引擎文件存放的路径,一般可设置为/,这样就可以指定绝对路径-->
<users_config>users.xml</users_config> <!--指定用户配置文件-->
<default_database>default</default_database> <!--指定默认数据库-->
<!--配置prometheus信息-->
<prometheus>
<endpoint>/metrics</endpoint>
<port>9363</port>
<metrics>true</metrics>
<events>true</events>
<asynchronous_metrics>true</asynchronous_metrics>
<status_info>true</status_info>
</prometheus>
<include_from>/etc/clickhouse-server/metrika.xml</include_from> <!--指定metrika.xml配置文件-->
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
# users.xml
<users>
<!--用户名为ck-->
<ck>
<password>123456</password> <!--明文密码-->
<!--
SHA256加密密码,可通过下面的命令生成:
PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-'
<password_sha256_hex>8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92</password_sha256_hex>
SHA1加密方式加密的密码,可通过下面的命令生成
PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
<password_double_sha1_hex>7c4a8d09ca3762af61e59520943dc26494f8941b</password_double_sha1_hex>
-->
<networks>
<ip>::/0</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</ck>
</users>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# metrika.xml
metrika.xml
主要是用来服务于集群搭建的。它里面是关于zookeeper
、shard
以及replica
的配置,比较复杂,将在部署集群中详细说明。
# 日志文件路径
默认的日志文件路径是:/var/log/clickhouse-server/
# 启动服务
- 后台服务启动:
systemctl start clickhouse-server
- 前端服务启动:
clickhouse-server start
systemctl start clickhouse-server
[root@node5 ck]# clickhouse-client
ClickHouse client version 20.9.3.45 (official build).
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 20.9.3 revision 54439.
node5 :) select 1
SELECT 1
┌─1─┐
│ 1 │
└───┘
1 rows in set. Elapsed: 0.003 sec.
node5 :)
2
3
4
5
6
7
8
9
10
11
12
13
# clickhouse-client
ClickHouse安装包中提供了clickhouse-client工具,这个客户端在运行shell环境中,使用TCP 方式连接clickhouse-server服务。
clickhouse-client
是一个带命令行的客户端工具,它通过TCP
的9000
端口连接clickhouse-server
,可以在该命令行工具里进行各种操作。通过 clickhouse-client --help
可以查看工具的帮助文档,可以看到该工具支持很多参数,此处简要说一下一些常用的参数。
要运行该客户端工具可以选择使用交互式与非交互式(批量)两种模式:
- 使用非交互式查询时需要指定--query参数;
- 在交互模式下则需要注意是否使用—mutiline参数来开启多行模式。
# 参数介绍
clickhouse-client提供了很多参数可供使用,常用的
- --host,-h 服务端的 host 名称, 默认是 'localhost'。 您可以选择使用 host 名称或者 IPv4 或 IPv6 地址。
- --port 连接服务端的端口,默认值9000
- --user,-u 访问的用户名,默认default
- --password 访问用户的密码,默认空字符串
- --query,-q 非交互模式下的查询语句
- --database,-d 连接的数据库,默认是default
- --multiline,-m 使用多行模式,在多行模式下,回车键仅表示换行。默认不使用多行模式。
- --multiquery,-n 使用”,”分割的多个查询,仅在非交互模式下有效
- --format, -f 使用指定格式化输出结果
- --vertical, -E 使用垂直格式输出,即每个值使用一行显示
- --time, -t 打印查询时间到stderr中
- --stacktrace 如果出现异常,会打印堆栈跟踪信息
- --config-file 使用指定配置文件
- --use_client_time_zone 使用服务端时区
- quit,exit 表示退出客户端
- Ctrl+D,Ctrl+C 表示退出客户端
参数 | 用法举例 | 说明 | 备注 |
---|---|---|---|
-h [ --host ]. | -h 192.168.0.1 --host=192.168.0.1| 指定连接 clickhouse服务的 host地址,一般是远程连接其他机器上的 clickhouse服务。 | clickhouse要想连接远程服务器,需要将配置文件中 <listen_host>::</listen_host>`选项开启。 | |||
--port | --port=9000 | 指定远程连接clickhouse 服务的端口号,默认为9000 | 这个端口号可通过配置文件配置:<tcp_port>9000</tcp_port> |
-u [ --user ]. | -u ck --user=ck| 指定登录 clickhouse的用户,默认是 default| default用户是内置的用户。可以通过 users.xml`配置文件自定义用户信息。 | |||
--password | --password=123456 | 指定登录clickhouse 的密码 | default 用户是没有密码的。密码可配置明文密码和加密密码 |
-q [ --query ] | -q "show databases" | 通过命令行直接输入sql ,即时返回,而不需要进入客户端内部 | |
-m [ --multiline ] | 在客户端内支持多行语句操作,以分号作为结束符 | 如果不指定-m 参数,每句sql 语法后可加分号,也可不加,默认一行就是一个语句 | |
-n [ --multiquery ] | 命令行直接输入语句时支持多条sql语句,一般和-q 结合使用 | 注意-n 的位置不能在-q 和sql 语句之间 | |
-f [ --format ] | -f JSON | 设置输出的显示格式 | 支持JSON 、CSV 、TSV 等,详见https://clickhouse.tech/docs/... (opens new window) |
# 登录命令
clickhouse-client -m --host node2.xxx.cn --port 9999 --user root --password 123456
# 导入数据
假设我们在default
数据库下有一张test
表,在/data01
目录下有一个file.csv
的文件,可通过如下方式将数据导入到test
表中。
clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV" < /data01/file.csv
# 部署集群
Clickhouse
的集群是依赖于zookeeper
的。所以在搭建clickhouse
集群之前,首先要有一个zookeeper
集群。
关于zookeeper
集群的搭建,此处不再展开详述,如有不清楚的请自行百度。(本文默认zookeeper
集群已经搭建好)
前面说过,clickhouse
集群的相关配置都在metrika.xml
配置文件里,所以首先我们需要配置好metrika.xml
。metrika.xml
的路径可以在config.xml
中通过<include_from>
指定。
# zookeeper配置
zookeeper
不一定要和ck
的节点安装在同一台机器上,只要ck
的几点能够访问zk即可。
<zookeeper-servers>
<node index="1">
<host>192.168.0.1</host>
<port>2181</port>
</node>
<node index="2">
<host>192.168.0.2</host>
<port>2181</port>
</node>
<node index="3">
<host>192.168.0.3</host>
<port>2181</port>
</node>
</zookeeper-servers>
2
3
4
5
6
7
8
9
10
11
12
13
14
# Shard和Replica设置
如下图所示,为一个完整的shard
和Replica
的配置,以下为test
集群配置2
分片2
副本。
<clickhouse_remote_servers>
<test> <!--集群的名字-->
<shard> <!--shard分片的配置-->
<internal_replication>true</internal_replication> <!--是否只将数据写入其中一个副本,默认为false-->
<replica> <!--shard副本的配置-->
<host>192.168.0.1</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.0.2</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>192.168.0.3</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.0.4</host>
<port>9000</port>
</replica>
</shard>
</test>
</clickhouse_remote_servers>
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
一个完整的metrika.xml
如下所示:
<yandex>
<zookeeper-servers>
<node index="1">
<host>192.168.0.1</host>
<port>2181</port>
</node>
<node index="2">
<host>192.168.0.2</host>
<port>2181</port>
</node>
<node index="3">
<host>192.168.0.3</host>
<port>2181</port>
</node>
</zookeeper-servers>
<clickhouse_remote_servers>
<test> <!--集群的名字-->
<shard> <!--shard分片的配置-->
<internal_replication>true</internal_replication> <!--是否只将数据写入其中一个副本,默认为false-->
<replica> <!--replica副本的配置-->
<host>192.168.0.1</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.0.2</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>192.168.0.3</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.0.4</host>
<port>9000</port>
</replica>
</shard>
</test>
</clickhouse_remote_servers>
</yandex>
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
# 集群搭建
首先按照单节点安装的方式,在node1
,node2
,node3
,node4
四个节点上安装好clickhouse
。
修改config.xml
,主要修改内容如下:
<!--1. 增加listen_host,允许远程访问-->
<listen_host>::</listen_host>
<!--2. 修改path路径,指定数据存放位置,我这里指定/data01/clickhouse目录-->
<!-- 需要注意的是,这个路径必须提前存在,且clickhouse用户有权限访问 -->
<path>/data01/clickhouse</path>
<tmp_path>/data01/clickhouse/tmp/</tmp_path>
<user_files_path>/data01/clickhouse/user_files/</user_files_path>
<access_control_path>/data01/clickhouse/access/</access_control_path>
<!--3.指定metrika.xml文件-->
<include_from>/etc/clickhouse-server/metrika.xml</include_from>
<!--4. 重新制定tcp_port -->
<tcp_port>19000</tcp_port>
<!--这一步不是必须的,我这里之所以重新制定,是因为发现我的机器上9000端口已经被占用了,一般情况下,默认的9000即可-->
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
修改users.xml
,我们增加一个用户,专门用来管理cluster
。
<!--在<users>里面新增如下内容,创建一个用户名为ck,密码为123456的用户-->
<ck>
<password>123456</password>
<networks incl="networks" replace="replace">
<ip>::/0</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</ck>
2
3
4
5
6
7
8
9
创建metrika.xml
文件。
在/etc/clickhouse-server
路径下创建metrika.xml
文件(这个路径为上面config.xml
中配置的include_from
的路径):
<yandex>
<zookeeper-servers>
<node index="1">
<host>192.168.0.1</host>
<port>2181</port>
</node>
<node index="2">
<host>192.168.0.2</host>
<port>2181</port>
</node>
<node index="3">
<host>192.168.0.3</host>
<port>2181</port>
</node>
</zookeeper-servers>
<clickhouse_remote_servers>
<test>
<shard>
<replica>
<host>192.168.0.1</host>
<port>9000</port> <!--这里的端口号要和config.xml中tcp_port保持一致,如果那里改了,这里也要对应的改-->
</replica>
<replica>
<host>192.168.0.2</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>192.168.0.3</host>
<port>9000</port>
</replica>
<replica>
<host>192.168.0.4</host>
<port>9000</port>
</replica>
</shard>
</test>
</clickhouse_remote_servers>
</yandex>
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
以上配置在四台机器上同步,然后重启clickhouse
:
systemctl restart clickhouse-server
如果启动成功,就能看到clickhouse-server
的进程已经在运行了:
[root@node2 test]# ps -ef |grep clickhouse
clickho+ 17548 1 1 11:11 ? 00:00:00 /usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid
root 17738 10683 0 11:11 pts/0 00:00:00 grep --color=auto clickhouse
2
3
我们使用clickhouse-client
工具,登录到其中一台机器:
[root@node4 test]# clickhouse-client -u ck --password=123456 -m
ClickHouse client version 20.9.3.45 (official build).
Connecting to localhost:9000 as user ck.
Connected to ClickHouse server version 20.9.3 revision 54439.
node4 :)
2
3
4
5
6
查询system.clusters
表:
node4 :) select * from system.clusters where cluster = 'test';
SELECT *
FROM system.clusters
WHERE cluster = 'test'
┌─cluster─┬─shard_num─┬─shard_weight─┬─replica_num─┬─host_name─────┬─host_address──┬──port─┬─is_local─┬─user────┬─default_database─┬─errors_count─┬─estimated_recovery_time─┐
│ test │ 1 │ 1 │ 1 │ 192.168.0.1 │ 192.168.0.1 │ 9000 │ 0 │ default │ │ 0 │ 0 │
│ test │ 1 │ 1 │ 2 │ 192.168.0.2 │ 192.168.0.2 │ 9000 │ 0 │ default │ │ 0 │ 0 │
│ test │ 2 │ 1 │ 1 │ 192.168.0.3 │ 192.168.0.3 │ 9000 │ 0 │ default │ │ 0 │ 0 │
│ test │ 2 │ 1 │ 2 │ 192.168.0.4 │ 192.168.0.4 │ 9000 │ 1 │ default │ │ 0 │ 0 │
└─────────┴───────────┴──────────────┴─────────────┴───────────────┴───────────────┴───────┴──────────┴─────────┴──────────────────┴──────────────┴─────────────────────────┘
4 rows in set. Elapsed: 0.002 sec.
2
3
4
5
6
7
8
9
10
11
12
13
14
出现上面所示的结果,说明配置集群成功。
# 分布式表
接下来就可以在集群里创建分布式表了。
首先在集群的各个节点创建本地表。
CREATE TABLE t_cluster ON CLUSTER test (
id Int16,
name String,
birth Date
)ENGINE = MergeTree()
PARTITION BY toYYYYMM(birth)
ORDER BY id;
2
3
4
5
6
7
登录到任意节点,执行以上sql
,出现如下提示,说明执行成功:
node4 :) CREATE TABLE default.t_cluster ON CLUSTER test ( id Int16, name String, birth Date )ENGINE = MergeTree() PARTITION BY toYYYYMM(birth) ORDER BY id;
CREATE TABLE default.t_cluster ON CLUSTER test
(
`id` Int16,
`name` String,
`birth` Date
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(birth)
ORDER BY id
┌─host──────────┬──port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ 192.168.0.1 │ 9000 │ 0 │ │ 3 │ 0 │
│ 192.168.0.2 │ 9000 │ 0 │ │ 2 │ 0 │
│ 192.168.0.3 │ 9000 │ 0 │ │ 1 │ 0 │
│ 192.168.0.4 │ 9000 │ 0 │ │ 0 │ 0 │
└───────────────┴───────┴────────┴───────┴─────────────────────┴──────────────────┘
4 rows in set. Elapsed: 0.108 sec.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
我们可以登录任意一台机器,都能查询到t_cluster
表,这就说明已经在test
集群上所有节点创建了一个t_cluster
本地表。
这个时候如果往t_cluster
表插入数据,仍然是在所在节点的本地表中操作,在其他集群中是无法看见的。
如我们在node1
节点插入如下数据:
node1 :) insert into t_cluster values(1, 'aa', '2021-02-01'), (2, 'bb', '2021-02-02');
INSERT INTO t_cluster VALUES
Ok.
2 rows in set. Elapsed: 0.002 sec.
2
3
4
5
6
7
在node1
节点查询:
node1 :) select * from t_cluster;
SELECT *
FROM t_cluster
┌─id─┬─name─┬──────birth─┐
│ 1 │ aa │ 2021-02-01 │
│ 2 │ bb │ 2021-02-02 │
└────┴──────┴────────────┘
2 rows in set. Elapsed: 0.002 sec.
2
3
4
5
6
7
8
9
10
11
node2
节点查询:
node2 :) select * from t_cluster;
SELECT *
FROM t_cluster
Ok.
0 rows in set. Elapsed: 0.002 sec.
2
3
4
5
6
7
8
node3
和node4
查询也是如此。
这就充分说明了如果直接操作t_cluster
表,操作的数据其实只是当前节点的数据。有人可能会有疑惑,我不是明明指定了node1
和node2
互为replica
吗?为什么node1
的数据也没有同步到node2
上面去?
这是因为我们的引擎指定的是MergerTree
,而不是ReplicaMergeTree
,如果指定的是ReplicaMergeTree
,的确是会同步到对应的replica
上面去的,但这里创建的仅仅是MergeTree
,这个引擎本身不具备同步副本的功能,所以node2
上并没有同步数据。
一般在实际应用中,创建分布式表指定的都是
Replica
的表,这里仅仅是做一个例子说明。
那么既然如此,这个集群中的表数据不能互相关联起来,不就失去了集群的意义了吗?
为了解决上面的问题,从而引入了分布式表。
分布式表的创建是这样的:
CREATE TABLE default.dist_t_cluster ON CLUSTER test as t_cluster engine = Distributed(test, default, t_cluster,rand());
Distributed
是一个特殊的引擎,用来创建分布式表。它本身具有四个参数,第一个参数表示集群的名字,第二个参数为数据库的名字,第三个参数为表的名字,第四个参数为sharding key
,它决定最终数据落在哪一个分片上,最后一个参数可以省略,如果省略,则实用配置文件中的weight
分片权重。
上面的语句就是创建一张名为dist_t_cluster
的分布式表,该分布式表是基于test
集群中的default.t_cluster
表。as t_cluster
表示这张表的结构和t_cluster
一模一样。
分布式表本身不存储数据,数据存储其实还是由本地表t_cluster
完成的。这个dist_t_cluster
仅仅做一个代理的作用。
如下所示,表示分布式表创建成功。
node1 :) CREATE TABLE default.dist_t_cluster ON CLUSTER test as t_cluster engine = Distributed(test, default, t_cluster, rand());
CREATE TABLE default.dist_t_cluster ON CLUSTER test AS t_cluster
ENGINE = Distributed(test, default, t_cluster, rand())
┌─host──────────┬──port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ 192.168.0.1 │ 9000 │ 0 │ │ 3 │ 0 │
│ 192.168.0.2 │ 9000 │ 0 │ │ 2 │ 0 │
│ 192.168.0.3 │ 9000 │ 0 │ │ 1 │ 0 │
│ 192.168.0.4 │ 9000 │ 0 │ │ 0 │ 0 │
└───────────────┴───────┴────────┴───────┴─────────────────────┴──────────────────┘
4 rows in set. Elapsed: 0.106 sec.
2
3
4
5
6
7
8
9
10
11
12
13
接下来我们使用分布式表向集群中插入数据,观察现象:
node1 :) insert into dist_t_cluster values(1, 'aaa', '2021-02-01'), (2, 'bbb', '2021-02-02');
INSERT INTO dist_t_cluster VALUES
Ok.
2 rows in set. Elapsed: 0.002 sec.
2
3
4
5
6
7
这时候我们在不同节点上查询dist_t_cluster
表,得到的结果都是一模一样的:
/* node1 查询结果 */
node1 :) select * from dist_t_cluster;
SELECT *
FROM dist_t_cluster
┌─id─┬─name─┬──────birth─┐
│ 2 │ bbb │ 2021-02-02 │
└────┴──────┴────────────┘
┌─id─┬─name─┬──────birth─┐
│ 1 │ aaa │ 2021-02-01 │
└────┴──────┴────────────┘
2 rows in set. Elapsed: 0.005 sec.
/* node2 查询结果 */
node2 :) select * from dist_t_cluster;
SELECT *
FROM dist_t_cluster
┌─id─┬─name─┬──────birth─┐
│ 2 │ bbb │ 2021-02-02 │
└────┴──────┴────────────┘
┌─id─┬─name─┬──────birth─┐
│ 1 │ aaa │ 2021-02-01 │
└────┴──────┴────────────┘
2 rows in set. Elapsed: 0.005 sec.
/* node3 查询结果 */
node3 :) select * from dist_t_cluster;
SELECT *
FROM dist_t_cluster
┌─id─┬─name─┬──────birth─┐
│ 1 │ aaa │ 2021-02-01 │
└────┴──────┴────────────┘
┌─id─┬─name─┬──────birth─┐
│ 2 │ bbb │ 2021-02-02 │
└────┴──────┴────────────┘
2 rows in set. Elapsed: 0.006 sec.
/* node4 查询结果 */
node4 :) select * from dist_t_cluster;
SELECT *
FROM dist_t_cluster
┌─id─┬─name─┬──────birth─┐
│ 1 │ aaa │ 2021-02-01 │
└────┴──────┴────────────┘
┌─id─┬─name─┬──────birth─┐
│ 2 │ bbb │ 2021-02-02 │
└────┴──────┴────────────┘
2 rows in set. Elapsed: 0.005 sec.
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
我们再去看各个节点的本地表t_cluster
表中数据分布情况:
/* node1 查询结果 */
node1 :) select * from t_cluster;
SELECT *
FROM t_cluster
┌─id─┬─name─┬──────birth─┐
│ 2 │ bbb │ 2021-02-02 │
└────┴──────┴────────────┘
1 rows in set. Elapsed: 0.002 sec.
/* node2 查询结果 */
node2 :) select * from t_cluster;
SELECT *
FROM t_cluster
┌─id─┬─name─┬──────birth─┐
│ 2 │ bbb │ 2021-02-02 │
└────┴──────┴────────────┘
1 rows in set. Elapsed: 0.002 sec.
/* node3 查询结果 */
node3 :) select * from t_cluster;
SELECT *
FROM t_cluster
┌─id─┬─name─┬──────birth─┐
│ 1 │ aaa │ 2021-02-01 │
└────┴──────┴────────────┘
1 rows in set. Elapsed: 0.002 sec.
/* node4 查询结果 */
node4 :) select * from t_cluster;
SELECT *
FROM t_cluster
┌─id─┬─name─┬──────birth─┐
│ 1 │ aaa │ 2021-02-01 │
└────┴──────┴────────────┘
1 rows in set. Elapsed: 0.002 sec.
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
由以上结果可知,node1
和node2
上面存储的数据一样,node3
和node4
上面存储的数据一样,但是node1
和node3
上面的数据不一样。node1
(node2
)和node3
(node4
)的数据组成了dist_t_cluster
表中的所有数据。
这是因为node1
和node2
、node3
和 node4
互为副本,所以它们的数据会自动同步。而node1
(node2
)和node3
(node4
)属于不同的分片,所以数据按照一定的规则(sharding key
)落在了不同分片。
如果我们打开存储数据的目录,可以看到dist_t_cluster
表中仅仅有一个临时文件夹,并没有实际存储数据,因为数据是存储在t_cluster
本地表中的。
[root@node1 chenyc]# ls -l /data01/clickhouse/data/default/dist_t_cluster/
总用量 0
drwxr-x--- 3 clickhouse clickhouse 17 2月 25 13:57 default@192%2E168%2E21%2E52:9000
drwxr-x--- 3 clickhouse clickhouse 17 2月 25 13:57 default@192%2E168%2E21%2E53:9000
drwxr-x--- 2 clickhouse clickhouse 6 2月 25 13:57 default@192%2E168%2E21%2E54:9000
2
3
4
5
# macros设置
macros
翻译过来是宏的意思,也就是通过它,可以使用一些宏定义在SQL
变量中进行替换,比如shard number
,replica
的名称等。这一点在需要创建Replicated
引擎表的时候特别有用。
Replicated
引擎有两个参数,其中一个为zoo_path
,表示zookeeper
中该表的路径;另一个参数为replica_name
,代表该表所在的副本名称。
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{cluster}/{shard}/default/dbtest', '{replica}')
order by (xxxx);
2
如上所示,就是一个Replicated
引擎在创建表时需要指定的参数。
其中:
参数 | 说明 |
---|---|
/clickhouse/tables | clickhouse在zookeeper的官方路径 |
{cluster} | 集群名称 |
{shard} | shard number |
default | 数据库名 |
dbtest | 表名,最好跟实际的表名一致 |
{replica} | 副本名称 |
先假设我们不设置macros
,如果我们要在node1
~node4
四个节点上创建Replicated
表,其中node1
和node2
位于shard1
,node3
和node4
位于shard2
,node1
与node2
互为副本,node3
与node4
互为副本。需要怎么创建?
我们需要在node1
上创建表dbtest
,语句如下:
CREATE TABLE dbtest(
...
)ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/1/default/dbtest', 'node1')
order by (xxxx);
2
3
4
然后在node2
~node4
上分别创建dbtest
表:
/*node2执行*/
CREATE TABLE dbtest(
...
)ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/1/default/dbtest', 'node2')
order by (xxxx);
/*node3执行*/
CREATE TABLE dbtest(
...
)ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/2/default/dbtest', 'node3')
order by (xxxx);
/*node4执行*/
CREATE TABLE dbtest(
...
)ENGINE = ReplicatedMergeTree('/clickhouse/tables/test/2/default/dbtest', 'node4')
order by (xxxx);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如果集群里节点特别多,那么这样到每个节点下去执行,实在太过累人。那么,有没有一种方式使用上面的类似 ON CLUSTER
的方式自动创建呢?
答案当然是有,这个时候就要借助macros
宏了。
我们可以在metrika.xml
文件中预先编写好一些宏,然后在SQL
变量中使用{}
括起来直接替换即可。
在metrika.xml
中配置宏如下所示:
<macros>
<cluster>test</cluster>
<shard>1</shard>
<replica>vm10140</replica>
</macros>
2
3
4
5
有了以上配置,那么在Replicated
引擎中传参的时候,就可以使用{cluster}
代替test
,使用{shard}
代替1
,用{replica}
代替vm10140
。我们只需要在不同节点上配置好对应的宏变量,那么,在创建Replicated
引擎表的时候,使用下面的语句就可以了:
CREATE TABLE dbtest ON CLUSTER test(
...
)ENGINE = ReplicatedMergeTree('/clickhouse/tables/{cluster}/{shard}/default/dbtest', '{replica}')
order by (xxxx);
2
3
4
以上语句在执行的时候,在node1
下,{cluster}
、{shard}
和{replica}
取的是node1
的宏对应的值,在node2
下取的是node2
的宏设置的值,自动替换,非常方便。
只要macros
配置正确,就可以使用上述语句在集群的各个节点去创建表了,而不必到每个节点下去手动创建一遍。
此时,我们通过zookeeper
可以查看到Replicated
中zoo_path
的具体情况:
顺便一提,macros
的信息都保存在system.macros
表中:
vm10140 :) select * from system.macros;
SELECT *
FROM system.macros
┌─macro───┬─substitution─┐
│ cluster │ test │
│ replica │ vm10140 │
│ shard │ 1 │
└─────────┴──────────────┘
3 rows in set. Elapsed: 0.005 sec.
2
3
4
5
6
7
8
9
10
11
12
因此,可以非常方便地从这个地方看到哪些宏是可以用的。
# 参考链接
- http://www.clickhouse.com.cn/
- https://segmentfault.com/a/1190000039291994