ClickHouse安装及集群搭建

本文介绍如何在CentOS系统上安装ClickHouse以及集群部署。

本文依赖的环境为CentOS-7.4.1708, 使用clickhouse的版本为20.9.3.45

单节点安装

在线yum安装

clickhouse的安装包并不在Linux官方yum仓库中,所以首先需要添加clickhouseyum镜像:

curl -s https://packagecloud.io/install/repositories/altinity/clickhouse/script.rpm.sh | sudo bash

检查镜像情况:

[root@master ~]# yum list | grep clickhouse
clickhouse-client.x86_64                 20.8.3.18-1.el7               Altinity_clickhouse
clickhouse-common-static.x86_64          20.8.3.18-1.el7               Altinity_clickhouse
clickhouse-debuginfo.x86_64              20.1.11.73-1.el7              Altinity_clickhouse
clickhouse-odbc.x86_64                   1.1.9-1.el7                   Altinity_clickhouse
clickhouse-server.x86_64                 20.8.3.18-1.el7               Altinity_clickhouse
clickhouse-server-common.x86_64          20.8.3.18-1.el7               Altinity_clickhouse
clickhouse-test.x86_64                   20.8.3.18-1.el7               Altinity_clickhouse
clicktail.x86_64                         1.0.20180401-1                Altinity_clickhouse

由此可见,使用yum在线安装的版本最新到20.8.3.18。但是实际上clickhouse已经迭代了很多版本,所以我们不采用此种安装方式,而采用rpm包的安装方式。

PS: 有了上面的信息, yum方式安装 clickhouse就很简单了,直接 yum install -y clickhouse-server-common.x86_64 clickhouse-server.x86_64 clickhouse-client.x86_64安装即可,此处就不演示了。

rpm包离线安装

我们可以从官方rpm镜像仓库找到各种版本的rpm安装包,官方地址是:https://repo.yandex.ru/clickh...

我们选择 20.9.3.45 版本的rpm包,主要需要以下三个包:

clickhouse-client-20.9.3.45-2.noarch.rpm
clickhouse-server-20.9.3.45-2.noarch.rpm
clickhouse-common-static-20.9.3.45-2.x86_64.rpm

安装命令如下:

rpm -ivh clickhouse-common-static-20.9.3.45-2.x86_64.rpm clickhouse-client-20.9.3.45-2.noarch.rpm clickhouse-server-20.9.3.45-2.noarch.rpm

如下图所示,我们即在node5这台机器上安装好了clickhouse

[root@node5 ck]# rpm -ivh clickhouse-common-static-20.9.3.45-2.x86_64.rpm clickhouse-client-20.9.3.45-2.noarch.rpm clickhouse-server-20.9.3.45-2.noarch.rpm
警告:clickhouse-common-static-20.9.3.45-2.x86_64.rpm: 头V4 RSA/SHA1 Signature, 密钥 ID e0c56bd4: NOKEY
准备中...                          ################################# [100%]
正在升级/安装...
   1:clickhouse-common-static-20.9.3.4################################# [ 33%]
   2:clickhouse-client-20.9.3.45-2    ################################# [ 67%]
   3:clickhouse-server-20.9.3.45-2    ################################# [100%]
Path to data directory in /etc/clickhouse-server/config.xml: /var/lib/clickhouse/
[root@node5 ck]# 

验证是否安装成功

如果以上步骤没有报错,则可以通过如下命令开启clickhouse的服务:

systemctl start clickhouse-server

然后通过clickhouse-client客户端去连接:

[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 :) 

如果出现上述界面,则说明单机安装clickhouse成功。

clickhouse-client CLI工具说明

在上面,我们用到了clickhouse-client这样一款工具。

clickhouse-client是一个带命令行的客户端工具,它通过TCP9000端口连接clickhouse-server,可以在该命令行工具里进行各种操作。

通过 clickhouse-client --help可以查看工具的帮助文档,可以看到该工具支持很多参数,此处简要说一下一些常用的参数。

参数 用法举例 说明 备注
-h [ --host ] -h 192.168.0.1
--host=192.168.0.1
指定连接clickhouse服务的host地址,一般是远程连接其他机器上的clickhouse服务。 clickhouse要想连接远程服务器,需要将配置文件中::选项开启。
--port --port=9000 指定远程连接clickhouse服务的端口号,默认为9000 这个端口号可通过配置文件配置:9000
-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的位置不能在-qsql语句之间
-f [ --format ] -f JSON 设置输出的显示格式 支持JSONCSVTSV等,详见https://clickhouse.tech/docs/...

利用CLI工具导入数据

假设我们在default数据库下有一张test表,在/data01目录下有一个file.csv的文件,可通过如下方式将数据导入到test表中。

clickhouse-client --database=test --query="INSERT INTO test FORMAT CSV" < /data01/file.csv

配置文件说明

config.xml

config.xml文件是clickhouse默认的配置文件,路径为/etc/clickhouse-server/config.xml

config.xml中可以配置的内容有很多,下面节选一些比较重要的配置项来说明一下:



    
        
        trace
        /var/log/clickhouse-server/clickhouse-server.log 
        /var/log/clickhouse-server/clickhouse-server.err.log
        1000M
        10
    
    
    8123   
    9000     
    9004 

    ::  
    
    
    /var/lib/clickhouse/  
    
    /var/lib/clickhouse/user_files/  
    
    users.xml 
    
    default  
    
    
         
        /metrics
        9363
        true
        true
        true
        true
    
    
    /etc/clickhouse-server/metrika.xml  

users.xml


    
        
        123456  
        
        
              ::/0
              
        default
        default
    

metrika.xml

metrika.xml 主要是用来服务于集群搭建的。它里面是关于zookeepershard以及replica的配置,比较复杂,将在部署集群中详细说明。

部署集群

Clickhouse 的集群是依赖于zookeeper的。所以在搭建clickhouse集群之前,首先要有一个zookeeper集群。

关于zookeeper集群的搭建,此处不再展开详述,如有不清楚的请自行百度。(本文默认zookeeper集群已经搭建好)

前面说过,clickhouse集群的相关配置都在metrika.xml配置文件里,所以首先我们需要配置好metrika.xmlmetrika.xml的路径可以在config.xml中通过指定。

zookeeper配置

zookeeper 不一定要和ck的节点安装在同一台机器上,只要ck的几点能够访问zk即可。


    
      192.168.0.1
      2181
    
    
      192.168.0.2
      2181
    
    
      192.168.0.3
      2181
    
  

Shard和Replica设置

如下图所示,为一个完整的shardReplica的配置,以下为test集群配置2分片2副本。


          
         
        true  
           
          192.168.0.1
          9000
        
        
          192.168.0.2
          9000
        
      
      
        true
        
          192.168.0.3
          9000
        
        
          192.168.0.4
          9000
        
      
    
  

一个完整的metrika.xml如下所示:


    
    
      192.168.0.1
      2181
    
    
      192.168.0.2
      2181
    
    
      192.168.0.3
      2181
    
  
  
          
         
        true  
           
          192.168.0.1
          9000
        
        
          192.168.0.2
          9000
        
      
      
        true
        
          192.168.0.3
          9000
        
        
          192.168.0.4
          9000
        
      
    
  

集群搭建

首先按照单节点安装的方式,在node1node2node3node4四个节点上安装好clickhouse

修改config.xml,主要修改内容如下:


0.0.0.0   




/data01/clickhouse
/data01/clickhouse/tmp/
/data01/clickhouse/user_files/
/data01/clickhouse/access/


/etc/clickhouse-server/metrika.xml



19000

修改users.xml,我们增加一个用户,专门用来管理cluster


        
            123456
            
                ::/0
            
            default
            default
        

创建metrika.xml文件。

在/etc/clickhouse-server路径下创建metrika.xml文件(这个路径为上面config.xml中配置的include_from的路径):


    
    
      192.168.0.1
      2181
    
    
      192.168.0.2
      2181
    
    
      192.168.0.3
      2181
    
  
  
          
         
          
          192.168.0.1
          19000    
        
        
          192.168.0.2
          19000
        
      
      
        
          192.168.0.3
          19000
        
        
          192.168.0.4
          19000
        
      
    
  

以上配置在四台机器上同步,然后重启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

我们使用clickhouse-client工具,登录到其中一台机器:

[root@node4 test]# clickhouse-client -u ck --password=123456 --port=19000 -m
ClickHouse client version 20.9.3.45 (official build).
Connecting to localhost:19000 as user ck.
Connected to ClickHouse server version 20.9.3 revision 54439.

node4 :) 

查询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 │ 19000 │        0 │ default │                  │            0 │                       0 │
│ test    │         1 │            1 │           2 │ 192.168.0.2 │ 192.168.0.2 │ 19000 │        0 │ default │                  │            0 │                       0 │
│ test    │         2 │            1 │           1 │ 192.168.0.3 │ 192.168.0.3 │ 19000 │        0 │ default │                  │            0 │                       0 │
│ test    │         2 │            1 │           2 │ 192.168.0.4 │ 192.168.0.4 │ 19000 │        1 │ default │                  │            0 │                       0 │
└─────────┴───────────┴──────────────┴─────────────┴───────────────┴───────────────┴───────┴──────────┴─────────┴──────────────────┴──────────────┴─────────────────────────┘

4 rows in set. Elapsed: 0.002 sec.

出现上面所示的结果,说明配置集群成功。

分布式表

接下来就可以在集群里创建分布式表了。

首先在集群的各个节点创建本地表。

CREATE TABLE t_cluster ON CLUSTER test (
id Int16,
name String,
birth Date
)ENGINE = MergeTree()
PARTITION BY toYYYYMM(birth)
ORDER BY id;

登录到任意节点,执行以上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 │ 19000 │      0 │       │                   3 │                0 │
│ 192.168.0.2 │ 19000 │      0 │       │                   2 │                0 │
│ 192.168.0.3 │ 19000 │      0 │       │                   1 │                0 │
│ 192.168.0.4 │ 19000 │      0 │       │                   0 │                0 │
└───────────────┴───────┴────────┴───────┴─────────────────────┴──────────────────┘

4 rows in set. Elapsed: 0.108 sec. 

我们可以登录任意一台机器,都能查询到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.

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. 

node2节点查询:

node2 :) select * from t_cluster;

SELECT *
FROM t_cluster

Ok.

0 rows in set. Elapsed: 0.002 sec.

node3node4查询也是如此。

这就充分说明了如果直接操作t_cluster表,操作的数据其实只是当前节点的数据。有人可能会有疑惑,我不是明明指定了node1node2互为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 │ 19000 │      0 │       │                   3 │                0 │
│ 192.168.0.2 │ 19000 │      0 │       │                   2 │                0 │
│ 192.168.0.3 │ 19000 │      0 │       │                   1 │                0 │
│ 192.168.0.4 │ 19000 │      0 │       │                   0 │                0 │
└───────────────┴───────┴────────┴───────┴─────────────────────┴──────────────────┘

4 rows in set. Elapsed: 0.106 sec.

接下来我们使用分布式表向集群中插入数据,观察现象:

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. 

这时候我们在不同节点上查询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.

我们再去看各个节点的本地表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. 

由以上结果可知,node1node2上面存储的数据一样,node3node4上面存储的数据一样,但是node1node3上面的数据不一样。node1node2)和node3node4)的数据组成了dist_t_cluster表中的所有数据。

这是因为node1node2node3node4互为副本,所以它们的数据会自动同步。而node1node2)和node3node4)属于不同的分片,所以数据按照一定的规则(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:19000
drwxr-x--- 3 clickhouse clickhouse 17 2月  25 13:57 default@192%2E168%2E21%2E53:19000
drwxr-x--- 2 clickhouse clickhouse  6 2月  25 13:57 default@192%2E168%2E21%2E54:19000

你可能感兴趣的:(ClickHouse安装及集群搭建)