1.概述
在Clickhouse 19.15
版本之前,MergeTree
只支持单路径存储,所有的数据都会被写入config.xml
配置中path指定的路径下,
即使服务器挂载了多块磁盘,也无法有效利用这些存储空间。
为了解决这种问题 在19.15
版本开始支持MergeTree
自定义存储策略的功能,支持以数据分区为最小移动单元将分区目录写入多
块磁盘目录。
根据配置策略的不同,目前大致有三类存储策略:
默认策略(default)
:MergeTree原本的存储策略,无须任何配置,所有分区会自动保存到config.xml 配置中的path指定的路径。JBOD策略
:这种策略适用于服务器挂载了多块磁盘,但是没有RAID的场景。JBOD (Just a Bunch Of Disks),是一种
Round-robin轮询策略
,每执行一次INSERT或者Merge 所产生的新分区会轮询写入各个磁盘。这种策略的效果类似于RAID 0,可以
降低单块磁盘的负载,在一定条件下能增加数据并行读写的性能。若单块磁盘发生故障,则会丢掉应用JBOD策略写入的这部分数据。HOT/COLD策略
:(冷热分离
)这种策略适合服务器挂载了不同类型磁盘的场景。将存储磁盘分为HOT和COLD。
HOT使用SSD,注重性能;
COLD区域使用HDD这类高容量存储媒介,注重存取的经济性。
数据在写入的MergeTree之初,首先会在HOT区域创建分区目录保存数据,当分区数据大小达到阈值数据会自动移动到COLD区域。
而在每个区域的内部也支持定义多个磁盘,所以在单个区域写入的过程,也能使用JBOD策略。
disks 配置示例:
<storage_configuration>
<disks>
<disk_name_1> <!-- disk name -->
<path>/mnt/fast_ssd/clickhouse/</path>
</disk_name_1>
<disk_name_2>
<path>/mnt/hdd1/clickhouse/</path>
<keep_free_space_bytes>10485760</keep_free_space_bytes>
</disk_name_2>
<disk_name_3>
<path>/mnt/hdd2/clickhouse/</path>
<keep_free_space_bytes>10485760</keep_free_space_bytes>
</disk_name_3>
...
</disks>
...
</storage_configuration>
解释:
<disk_name_*>
必填项,必须全局唯一,表示磁盘的自定义名称<path>
必填项,用于指定磁盘路<keep_free_space_bytes>
选填项,用于指定指定磁盘的预留空间,单位字节bit
注意:磁盘的配置选项的先后顺序没有关系。
在policies 的配置中,需要引用先前定义的disks磁盘。policies 同样支持定义多个策略。
policies策略示例:
<storage_configuration>
...
<policies>
<policy_name_1>
<volumes>
<volume_name_1>
<disk>disk_name_from_disks_configuration</disk>
<max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
</volume_name_1>
<volume_name_2>
<!-- configuration -->
</volume_name_2>
<!-- more volumes -->
</volumes>
<move_factor>0.2</move_factor>
</policy_name_1>
<policy_name_2>
<!-- configuration -->
</policy_name_2>
<!-- more policies -->
</policies>
...
</storage_configuration>
解释:
<policy_name_*>
必填项,必须全局唯一,表示策略的自定义名称<volume_name_*>
必填项,必须全局唯一,表示卷的自定义名称<disk>
必填项,用于关联配置内的磁盘,可以声明多个disk,MergeTree会按照定义的顺序选择disk<max_data_part_size_bytes>
选填,字节为单位 默认1G,表示在这个卷的单个disk磁盘中,一个数据分区的最大磁盘存储阈值,
若当前分区的数据大小超过阈值,则之后的分区会写入下一个disk磁盘。<move_factor>
选填项,默认值为0.1,;若当前卷的可用空间大小小于factor因子,并且定义多个卷,则数据会自动移动到下一个卷。
2.JBOD策略:
0.添加磁盘:
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
nvme0n1 259:0 0 60G 0 disk
├─nvme0n1p1 259:1 0 25G 0 part /opt
├─nvme0n1p2 259:2 0 15G 0 part /var
├─nvme0n1p3 259:3 0 10G 0 part /
├─nvme0n1p4 259:4 0 1K 0 part
└─nvme0n1p5 259:5 0 10G 0 part /data
1.在配置文件中配置config.xml ,为了避免升级操作服务文件建议写到/etc/clickhouse-server/config.d/ 下:
# mkdir -p /opt/clickhouse_hot{1,2}
# mkdir -p /data/clickhouse_cold
# mkdir -p /data/clickhouse_archive
配置文件:
-- 权限设置:
[root@hadoop101 config.d]# chown -R clickhouse:clickhouse /opt/clickhouse_hot*
[root@hadoop101 config.d]# chmod -R 775 /opt/clickhouse_hot*
[root@hadoop101 config.d]# chown -R clickhouse:clickhouse /data/clickhouse_cold
[root@hadoop101 config.d]# chmod -R 775 /data/clickhouse_cold/
[root@hadoop101 config.d]# chown -R clickhouse:clickhouse /data/clickhouse_archive
[root@hadoop101 config.d]# chmod -R 775 /data/clickhouse_archive/
– 重启clickhouse:
# systemctl restart clickhouse-server
# systemctl status clickhouse-server
● clickhouse-server.service - ClickHouse Server (analytic DBMS for big data)
Loaded: loaded (/etc/systemd/system/clickhouse-server.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-06-14 18:16:07 CST; 21s ago
Main PID: 6620 (clickhouse-serv)
CGroup: /system.slice/clickhouse-server.service
└─6620 /usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.xml --pid-file=/run/clickhouse-server/clickhouse-server.pid
若有问题可以通过日志进行排查:
sudo tail -n 10 /var/log/clickhouse-server/clickhouse-server.err.log
– 修改之前:
Clickhouse> SELECT name, path, formatReadableSize(free_space) AS free, formatReadableSize(total_space) AS total,formatReadableSize(keep_free_space) AS reserved FROM system.disks;
SELECT
name,
path,
formatReadableSize(free_space) AS free,
formatReadableSize(total_space) AS total,
formatReadableSize(keep_free_space) AS reserved
FROM system.disks
┌─name────┬─path─────────────────┬─free─────┬─total─────┬─reserved─┐
│ default │ /var/lib/clickhouse/ │ 7.01 GiB │ 14.99 GiB │ 0.00 B │
└─────────┴──────────────────────┴──────────┴───────────┴──────────┘
登陆查看:
磁盘:
Clickhouse> SELECT name, path, formatReadableSize(free_space) AS free, formatReadableSize(total_space) AS total,formatReadableSize(keep_free_space) AS reserved FROM system.disks;
SELECT
name,
path,
formatReadableSize(free_space) AS free,
formatReadableSize(total_space) AS total,
formatReadableSize(keep_free_space) AS reserved
FROM system.disks
┌─name──────┬─path───────────────────┬─free───────┬─total─────┬─reserved─┐
│ default │ /var/lib/clickhouse/ │ 7.15 GiB │ 14.99 GiB │ 1.00 KiB │
│ disk_cold │ /data/clickhouse_cold/ │ 205.93 MiB │ 9.99 GiB │ 0.00 B │
│ disk_hot1 │ /opt/clickhouse_hot1/ │ 15.17 GiB │ 24.99 GiB │ 0.00 B │
│ disk_hot2 │ /opt/clickhouse_hot2/ │ 15.17 GiB │ 24.99 GiB │ 0.00 B │
└───────────┴────────────────────────┴────────────┴───────────┴──────────┘
4 rows in set. Elapsed: 0.003 sec.
通过system.disks 查询可以看到声明的磁盘你配置已经生效。
策略查询:
SELECT policy_name, volume_name, disks
FROM system.storage_policies
┌─policy_name────┬─volume_name─────────┬─disks─────────────────────┐
│ default │ default │ ['default'] │
└────────────────┴─────────────────────┴───────────────────────────┘
Clickhouse> select policy_name,volume_name,volume_priority,disks,max_data_part_size,move_factor from system.storage_policies;
SELECT
policy_name,
volume_name,
volume_priority,
disks,
max_data_part_size,
move_factor
FROM system.storage_policies
┌─policy_name──┬─volume_name─┬─volume_priority─┬─disks─────────────────────┬─max_data_part_size─┬─move_factor─┐
│ JBOD_default │ disk_group │ 1 │ ['disk_hot1','disk_hot2'] │ 0 │ 0.1 │
│ default │ default │ 1 │ ['default'] │ 0 │ 0 │
└──────────────┴─────────────┴─────────────────┴───────────────────────────┴────────────────────┴─────────────┘
2 rows in set. Elapsed: 0.002 sec.
通过查询系统表可以看到配置到的存储策略生效。
注意:
测试:
Clickhouse> create table t_JBOD(id UInt64) engine=MergeTree() order by id settings storage_policy='JBOD_default';
-- 插入数据:
Clickhouse> insert into table t_JBOD select rand() from numbers(100);
Clickhouse> insert into table t_JBOD select rand() from numbers(10);
-- 查询分区系统表:
Clickhouse> select name,partition,disk_name,path from system.parts where table='t_JBOD';
SELECT
name,
partition,
disk_name,
path
FROM system.parts
WHERE table = 't_JBOD'
┌─name──────┬─partition─┬─disk_name─┬─path──────────────────────────────────────────────┐
│ all_1_1_0 │ tuple() │ disk_hot1 │ /opt/clickhouse_hot1/data/study/t_JBOD/all_1_1_0/ │
│ all_2_2_0 │ tuple() │ disk_hot2 │ /opt/clickhouse_hot2/data/study/t_JBOD/all_2_2_0/ │
└───────────┴───────────┴───────────┴───────────────────────────────────────────────────┘
2 rows in set. Elapsed: 0.003 sec.
Clickhouse> optimize table t_JBOD;
分区合并操作,生成一个合并后的新分区目录。
结论:
JBOD策略中由多个磁盘组成一个磁盘组(volume),每当生成一个新数据分区的时候,分区目录会按照volume中磁盘定义的顺序依次轮询并写入各个磁盘。
HOT/COLD 策略:
在配置文件中新增一个策略:完整的配置信息如下:
# cat /etc/clickhouse-server/config.d/cust_storage.xml
<yandex>
<storage_configuration>
<disks>
<!--
default disk is special, it always
exists even if not explicitly
configured here, but you can't change
it's path here (you should use <path>
on top level config instead)
-->
<default>
<!--
You can reserve some amount of free space
on any disk (including default) by adding
keep_free_space_bytes tag
-->
<keep_free_space_bytes>1024</keep_free_space_bytes>
</default>
<!-- 自定义磁盘配置 -->
<disk_hot1>
<!-- disk path must end with a slash,
folder should be writable for clickhouse user
-->
<path>/opt/clickhouse_hot1/</path>
</disk_hot1>
<disk_hot2>
<path>/opt/clickhouse_hot2/</path>
</disk_hot2>
<disk_cold>
<path>/data/clickhouse_cold/</path>
</disk_cold>
<disk_archive>
<path>/data/clickhouse_archive/</path>
</disk_archive>
</disks>
<policies>
<!-- 自定义策略名称 磁盘轮询 -->
<JBOD_default>
<volumes>
<disk_group>
<disk>disk_hot1</disk>
<disk>disk_hot2</disk>
</disk_group>
</volumes>
</JBOD_default>
<!-- 自定义策略名称 冷热分离-->
<default_hot_cold>
<volumes>
<hot>
<disk>disk_hot1</disk>
<disk>disk_hot2</disk>
<max_data_part_size_bytes>200000000</max_data_part_size_bytes>
</hot>
<cold>
<disk>disk_cold</disk>
<max_data_part_size_bytes>80000000000</max_data_part_size_bytes>
</cold>
<archive>
<disk>disk_archive</disk>
</archive>
</volumes>
<move_factor>0.2</move_factor>
</default_hot_cold>
</policies>
</storage_configuration>
</yandex>
需要重启服务:
[root@hadoop101 config.d]# systemctl restart clickhouse-server
[root@hadoop101 config.d]# systemctl status clickhouse-server
# clickhouse-client --multiline
-- 查询验证新配置的存储策略:
Clickhouse> select policy_name,volume_name,volume_priority,disks,formatReadableSize(max_data_part_size) max_data_part_size ,move_factor from system.storage_policies;
SELECT
policy_name,
volume_name,
volume_priority,
disks,
formatReadableSize(max_data_part_size) AS max_data_part_size,
move_factor
FROM system.storage_policies
┌─policy_name──────┬─volume_name─┬─volume_priority─┬─disks─────────────────────┬─max_data_part_size─┬─move_factor─┐
│ JBOD_default │ disk_group │ 1 │ ['disk_hot1','disk_hot2'] │ 0.00 B │ 0.1 │
│ default │ default │ 1 │ ['default'] │ 0.00 B │ 0 │
│ default_hot_cold │ hot │ 1 │ ['disk_hot1','disk_hot2'] │ 1.00 MiB │ 0.2 │
│ default_hot_cold │ cold │ 2 │ ['disk_cold'] │ 10.00 GiB │ 0.2 │
│ default_hot_cold │ archive │ 3 │ ['disk_archive'] │ 0.00 B │ 0.2 │
└──────────────────┴─────────────┴─────────────────┴───────────────────────────┴────────────────────┴─────────────┘
5 rows in set. Elapsed: 0.002 sec.
hot卷的max_data_part_size 大小为1M 在此磁盘卷下若有一个分区大小超过1M 则需要被移动到紧邻的下一个磁盘卷。
Clickhouse> create table t_hot_cold(id UInt64) engine=MergeTree() order by id settings storage_policy='default_hot_cold';
插入500k大小的数据:
Clickhouse> insert into table t_hot_cold select rand() from numbers(100000);
Clickhouse> select name,partition,disk_name,path from system.parts where table='t_hot_cold';
SELECT
name,
partition,
disk_name,
path
FROM system.parts
WHERE table = 't_hot_cold'
┌─name──────┬─partition─┬─disk_name─┬─path──────────────────────────────────────────────────┐
│ all_1_1_0 │ tuple() │ disk_hot1 │ /opt/clickhouse_hot1/data/study/t_hot_cold/all_1_1_0/ │
└───────────┴───────────┴───────────┴───────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.003 sec.
Clickhouse> optimize table t_hot_cold;
OPTIMIZE TABLE t_hot_cold
Ok.
0 rows in set. Elapsed: 0.017 sec.
Clickhouse> select name,partition,disk_name,path from system.parts where table='t_hot_cold';
SELECT
name,
partition,
disk_name,
path
FROM system.parts
WHERE table = 't_hot_cold'
┌─name──────┬─partition─┬─disk_name────┬─path──────────────────────────────────────────────────────┐
│ all_1_1_0 │ tuple() │ disk_hot1 │ /opt/clickhouse_hot1/data/study/t_hot_cold/all_1_1_0/ │
│ all_1_2_1 │ tuple() │ disk_archive │ /data/clickhouse_archive/data/study/t_hot_cold/all_1_2_1/ │
│ all_2_2_0 │ tuple() │ disk_hot2 │ /opt/clickhouse_hot2/data/study/t_hot_cold/all_2_2_0/ │
└───────────┴───────────┴──────────────┴───────────────────────────────────────────────────────────┘
3 rows in set. Elapsed: 0.005 sec.
由于hot磁盘卷的max_data_part_size 为 1M 前2词数据写入所创建的分区,单个分区大小为500KB,自然分区目录被保存到hot卷。
在执行强制合并分区操作之后,生成一个新的分区目录,所创建新分区的大小超过了1MB 这被写入archive卷。
Clickhouse> select disk_name ,formatReadableSize(bytes_on_disk) size from system.parts where table='t_hot_cold' and active=1;
SELECT
disk_name,
formatReadableSize(bytes_on_disk) AS size
FROM system.parts
WHERE (table = 't_hot_cold') AND (active = 1)
┌─disk_name────┬─size─────┐
│ disk_archive │ 1.01 MiB │
└──────────────┴──────────┘
1 rows in set. Elapsed: 0.011 sec.
-- 直接生成超过1M的数据:
insert into table t_hot_cold select rand() from numbers(200000)
Clickhouse> select name,partition,disk_name,path from system.parts where table='t_hot_cold';
SELECT
name,
partition,
disk_name,
path
FROM system.parts
WHERE table = 't_hot_cold'
┌─name──────┬─partition─┬─disk_name────┬─path──────────────────────────────────────────────────────┐
│ all_1_1_0 │ tuple() │ disk_hot1 │ /opt/clickhouse_hot1/data/study/t_hot_cold/all_1_1_0/ │
│ all_1_2_1 │ tuple() │ disk_archive │ /data/clickhouse_archive/data/study/t_hot_cold/all_1_2_1/ │
│ all_2_2_0 │ tuple() │ disk_hot2 │ /opt/clickhouse_hot2/data/study/t_hot_cold/all_2_2_0/ │
│ all_3_3_0 │ tuple() │ disk_archive │ /data/clickhouse_archive/data/study/t_hot_cold/all_3_3_0/ │
└───────────┴───────────┴──────────────┴───────────────────────────────────────────────────────────┘
4 rows in set. Elapsed: 0.002 sec.
可以看到一次性写入大于1M的数据则直接写入到cold/archive卷。
hot/cold 策略:在冷热分离策略中由多个磁盘卷(volume) 组成一个volume 组。每当生成一个新的数据分区的时候,按照阈值分区目录依照volume组中磁盘定义的顺序依次轮询
并写入各个卷下的磁盘。
MergeTree存储策略目前不能修改,但是分区目录却支持移动。
示例:将某个分区移动至当前存储策略中某个volume卷下的其他disk磁盘:
alter table t_hot_cold move part 'all_1_2_1' to DISK 'disk_hot1';
将某个分区移动至当前存储策略中其他的volume卷:
alter table t_hot_cold move part 'all_1_2_1' to DISK 'cold';