分片集群介绍
副本虽然能够提高数据的可用性,降低丢失风险,但是每台服务器实际上必须容纳全量数据,对数据的横向扩容没有解决。
要解决数据水平切分的问题,需要引入分片的概念。通过分片把一份完整的数据进行切分,不同的分片分布到不同的节点上,再通过 Distributed 表引擎把数据拼接起来一同使用。
Distributed 表引擎本身不存储数据,有点类似于 MyCat 之于 MySql,成为一种中间件,
通过分布式逻辑表来写入、分发、路由来操作多台节点不同分片的分布式数据
注意:Clickhouse的集群是表级别的,实际企业中,大部分做了高可用,但是没有分片,避免降低查询性能以及操作集群的复杂性。
集群写入流程
用户通过客户端进行写入操作,然后clickhouse会把写入的数据分配到各个分片存储到磁盘。
集群读取流程
读取操作副本选择机制:
- 优先选择errors_count小的副本
- errors_count相同的有随机、顺序、随机(优先第一顺位)、host名称近似等四种选择方式
分片集群安装
环境介绍
主机名 | IP | OS | software |
---|---|---|---|
clickhouse-1 | 192.168.1.104 | CentOS Linux release 7.7 | clickhouse,zookeeper |
clickhouse-2 | 192.168.1.105 | CentOS Linux release 7.7 | clickhouse,zookeeper |
clickhouse-3 | 192.168.1.106 | CentOS Linux release 7.7 | clickhouse,zookeeper |
clickhouse-4 | 192.168.1.107 | CentOS Linux release 7.7 | clickhouse |
clickhouse-5 | 192.168.1.108 | CentOS Linux release 7.7 | clickhouse |
clickhouse-6 | 192.168.1.109 | CentOS Linux release 7.7 | clickhouse |
准备工作
$ cat /etc/redhat-release # 查看系统版本
CentOS Linux release 7.7.1908 (Core)
# 关闭防火墙
$ systemctl stop firewalld.service
$ systemctl disable firewalld.service
# 配置打开文件数限制
# 在所有节点的 /etc/security/limits.conf 文件的末尾加入以下内容
$ vim /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072
# 在所有节点的 /etc/security/limits.d/20-nproc.conf 文件的末尾加入以下内容
$ vim /etc/security/limits.d/20-nproc.conf
* soft nofile 65536
* hard nofile 65536
* soft nproc 131072
* hard nproc 131072
# 安装依赖
$ yum install -y libtool
$ yum install -y *unixODBC*
# 关闭selinux:
$ sed -i 's/enforcing/disabled/' /etc/selinux/config
$ setenforce 0
# 关闭swap:
$ swapoff -a # 临时
$ sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久
# 根据规划设置主机名:
hostnamectl set-hostname <hostname>
# 配置hosts记录
cat <<EOF >> /etc/hosts
192.168.1.104 clickhouse-1
192.168.1.105 clickhouse-2
192.168.1.106 clickhouse-3
192.168.1.107 clickhouse-4
192.168.1.108 clickhouse-5
192.168.1.109 clickhouse-6
EOF
zookeeper集群安装
# 部署JDK1.8.0_262
$ wget -P /usr/local/src https://github.com/AdoptOpenJDK/openjdk8-upstream-binaries/releases/download/jdk8u262-b10/OpenJDK8U-jdk_x64_linux_8u262b10.tar.gz # 下载jdk安装包
$ cd /usr/local/src/
$ tar zxf OpenJDK8U-jdk_x64_linux_8u262b10.tar.gz # 解压jdk安装包
$ mv openjdk-8u262-b10 /application/
# 添加环境变量
$ cat << EOF >> /etc/profile
export JAVA_HOME=/application/openjdk-8u262-b10
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
EOF
$ source /etc/profile
$ java -version # 如出现如下则安装成功
openjdk version "1.8.0_262"
OpenJDK Runtime Environment (build 1.8.0_262-b10)
OpenJDK 64-Bit Server VM (build 25.262-b10, mixed mode)
### Zookeeper部署(所有节点执行)
```shell
# Zookeeper软件包下载并解压
$ wget -P /usr/local/src https://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.6.1/apache-zookeeper-3.6.1-bin.tar.gz
$ cd /usr/local/src/
$ tar zxf apache-zookeeper-3.6.1-bin.tar.gz
$ mv apache-zookeeper-3.6.1-bin /application/zookeeper
# 创建启动用户并创建存储目录
$ useradd -s /bin/bash -U zookeeper
$ mkdir -p /application/data/zookeeper-data/
$ chown -Rf zookeeper.zookeeper /application/data/zookeeper-data/
$ chown -Rf zookeeper.zookeeper /application/zookeeper
# 创建ServerID标识
$ echo '1' > /application/data/zookeeper-data/myid #clickhouse-1上执行
$ echo '2' > /application/data/zookeeper-data/myid #clickhouse-2上执行
$ echo '3' > /application/data/zookeeper-data/myid #clickhouse-3上执行
# 修改ZooKeeper配置
$ cat << EOF > /application/zookeeper/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/application/data/zookeeper-data
dataLogDir=/application/zookeeper/logs
clientPort=2181
maxClientCnxns=60
autopurge.snapRetainCount=3
autopurge.purgeInterval=1
server.1=192.168.1.104:2888:3888
server.2=192.168.1.105:2888:3888
server.3=192.168.1.106:2888:3888
EOF
# 创建zookeeper启动文件并启动
$ cat << EOF > /usr/lib/systemd/system/zookeeper.service
[Unit]
Description=zookeeper.service
After=network.target
[Service]
User=zookeeper
Group=zookeeper
Type=forking
ExecStart=/application/zookeeper/bin/zkServer.sh start
ExecStop=/application/zookeeper/bin/zkServer.sh stop
ExecReload=/application/zookeeper/bin/zkServer.sh restart
[Install]
EOF
$ systemctl start zookeeper.service # 启动zookeeper
$ systemctl enable zookeeper.service # 添加开机自启动
$ systemctl status zookeeper.service # 检测服务状态
```
到此ZK集群搭建完毕
Clickhouse安装
# 安装Clickhouse
$ yum install yum-utils
$ rpm --import https://repo.clickhouse.tech/CLICKHOUSE-KEY.GPG
$ yum-config-manager --add-repo https://repo.clickhouse.tech/rpm/clickhouse.repo
$ yum install clickhouse-server clickhouse-client
Clickhouse 分片集群配置
在所有节点的的/etc/clickhouse-server/config.d 目录下创建一个名为 metrika.xml 的配置文件,内容如下:
clickhouse-1:
[root@clickhouse-1 ~]# cat /etc/clickhouse-server/config.d/metrika.xml
<?xml version="1.0"?>
<yandex>
<zookeeper-servers>
<node index="1">
<host>192.168.1.104</host>
<port>2181</port>
</node>
<node index="2">
<host>192.168.1.105</host>
<port>2181</port>
</node>
<node index="3">
<host>192.168.1.106</host>
<port>2181</port>
</node>
</zookeeper-servers>
<remote_servers>
<gmall_cluster> <!-- 集群名称-->
<shard> <!--集群的第一个分片-->
<internal_replication>true</internal_replication>
<!--该分片的第一个副本-->
<replica>
<host>clickhouse-1</host>
<port>9000</port>
</replica>
<!--该分片的第二个副本-->
<replica>
<host>clickhouse-2</host>
<port>9000</port>
</replica>
</shard>
<shard> <!--集群的第二个分片-->
<internal_replication>true</internal_replication>
<!--该分片的第一个副本-->
<replica>
<host>clickhouse-3</host>
<port>9000</port>
</replica>
<!--该分片的第二个副本-->
<replica>
<host>clickhouse-4</host>
<port>9000</port>
</replica>
</shard>
<shard> <!--集群的第三个分片-->
<internal_replication>true</internal_replication>
<!--该分片的第一个副本-->
<replica>
<host>clickhouse-5</host>
<port>9000</port>
</replica>
<!--该分片的第二个副本-->
<replica>
<host>clickhouse-6</host>
<port>9000</port>
</replica>
</shard>
</gmall_cluster>
</remote_servers>
<macros>
<shard>01</shard> <!--不同机器放的分片数不一样-->
<replica>rep_1_1</replica> <!--不同机器放的副本数不一样-->
</macros>
</yandex>
clickhouse-2:
[root@clickhouse-2 ~]# cat /etc/clickhouse-server/config.d/metrika.xml
......
<macros>
<shard>01</shard> <!--不同机器放的分片数不一样-->
<replica>rep_1_2</replica> <!--不同机器放的副本数不一样-->
</macros>
</yandex>
clickhouse-3:
[root@clickhouse-3 ~]# cat /etc/clickhouse-server/config.d/metrika.xml
......
<macros>
<shard>02</shard> <!--不同机器放的分片数不一样-->
<replica>rep_1_3</replica> <!--不同机器放的副本数不一样-->
</macros>
</yandex>
clickhouse-4:
[root@clickhouse-4 ~]# cat /etc/clickhouse-server/config.d/metrika.xml
......
<macros>
<shard>02</shard> <!--不同机器放的分片数不一样-->
<replica>rep_1_4</replica> <!--不同机器放的副本数不一样-->
</macros>
</yandex>
clickhouse-5:
[root@clickhouse-5 ~]# cat /etc/clickhouse-server/config.d/metrika.xml
......
<macros>
<shard>03</shard> <!--不同机器放的分片数不一样-->
<replica>rep_1_5</replica> <!--不同机器放的副本数不一样-->
</macros>
</yandex>
clickhouse-6:
[root@clickhouse-6 ~]# cat /etc/clickhouse-server/config.d/metrika.xml
......
<macros>
<shard>03</shard> <!--不同机器放的分片数不一样-->
<replica>rep_1_6</replica> <!--不同机器放的副本数不一样-->
</macros>
</yandex>
在所有节点的的/etc/clickhouse-server/config.xml 中修改配置
726 <zookeeper incl="zookeeper-servers" optional="true" />
727 <include_from>/etc/clickhouse-server/config.d/metrika.xml</include_from>
162 <listen_host>0.0.0.0</listen_host>
启动clickhouse集群在所有节点中执行:
$ /etc/init.d/clickhouse-server start # 启动服务
$ /etc/init.d/clickhouse-server status # 查看服务状态
Clickhouse 分片集群验证
在clickhouse集群其中一个节点上执行建表语句:
-
会自动同步到所有节点 上
-
集群名字要和配置文件中的一致
-
分片和副本名称从配置文件的宏定义中获取
# 创建本地表
CREATE TABLE st_order_mt ON CLUSTER gmall_cluster
(
`id` UInt32,
`sku_id` String,
`total_amount` Decimal(16, 2),
`create_time` Datetime
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/st_order_mt', '{replica}')
PARTITION BY toYYYYMMDD(create_time)
PRIMARY KEY id
ORDER BY (id, sku_id)
Query id: 5c57420d-2294-43cc-8338-0383009fa934
┌─host─────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ clickhouse-2 │ 9000 │ 0 │ │ 5 │ 0 │
│ clickhouse-6 │ 9000 │ 0 │ │ 4 │ 0 │
│ clickhouse-4 │ 9000 │ 0 │ │ 3 │ 0 │
│ clickhouse-5 │ 9000 │ 0 │ │ 2 │ 0 │
│ clickhouse-1 │ 9000 │ 0 │ │ 1 │ 0 │
│ clickhouse-3 │ 9000 │ 0 │ │ 0 │ 0 │
└──────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
6 rows in set. Elapsed: 0.272 sec.
# 创建 Distribute 分布式表
create table st_order_mt_all2 on cluster gmall_cluster
(
id UInt32,
sku_id String,
total_amount Decimal(16,2),
create_time Datetime
)engine = Distributed(gmall_cluster,default, st_order_mt,hiveHash(sku_id));
参数含义:
Distributed(集群名称,库名,本地表名,分片键)
分片键必须是整型数字,所以用 hiveHash 函数转换,也可以 rand()
插入测试数据:
insert into st_order_mt_all2 values
(201,'sre_001',1000.00,'2021-06-01 12:00:00') ,
(202,'sre_002',2000.00,'2021-06-01 12:00:00'),
(203,'sre_004',2500.00,'2021-06-01 12:00:00'),
(204,'sre_002',2000.00,'2021-06-01 12:00:00'),
(205,'sre_003',600.00,'2021-06-02 12:00:00');
验证:
- 查询分布式表的数据是否完整
- 相同分片的副本是否一致
如上两点验证通过则分片集群部署完毕,一切就绪!
# 查看分布式表
clickhouse-1 :) SELECT * FROM st_order_mt_all2;
SELECT *
FROM st_order_mt_all2
Query id: 503aaa31-a7bf-4388-92b5-2760d4c843bf
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 205 │ sre_003 │ 600.00 │ 2021-06-02 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 202 │ sre_002 │ 2000.00 │ 2021-06-01 12:00:00 │
│ 204 │ sre_002 │ 2000.00 │ 2021-06-01 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 201 │ sre_001 │ 1000.00 │ 2021-06-01 12:00:00 │
│ 203 │ sre_004 │ 2500.00 │ 2021-06-01 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
5 rows in set. Elapsed: 0.013 sec.
# 查看第一个分片的副本数据
clickhouse-1 :) SELECT * FROM st_order_mt;
SELECT *
FROM st_order_mt
Query id: 52e669b2-5e94-42f2-969d-2c8d4829b83d
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 205 │ sre_003 │ 600.00 │ 2021-06-02 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
1 rows in set. Elapsed: 0.003 sec.
clickhouse-2 :) SELECT * FROM st_order_mt;
SELECT *
FROM st_order_mt
Query id: bfa393ef-b317-4cc7-8849-5d52dbf317e3
┌──id─┬─sku_id──┬─total_amount─┬─────────create_time─┐
│ 205 │ sre_003 │ 600.00 │ 2021-06-02 12:00:00 │
└─────┴─────────┴──────────────┴─────────────────────┘
1 rows in set. Elapsed: 0.004 sec.
评论区