来源:安瑞哥是码农
之所以说它奇葩,原因在于对于一个数据库来说,我头一次遇到,如果要对数据的存储目录(磁盘)设置多个的话,会这么麻烦。
为什么会突然注意到这个问题,原因在于之前部署的 clickhouse (下称 CK) 集群,为了方便,其数据存储路径只配置了一个(一块磁盘),但是随着数据的持续写入,发现这块盘的磁盘空间逐渐开始遭不住了。
于是想着,再给它额外添加2个目录,毕竟,我这服务器上还有另外2块磁盘没有用上呢。
但是,就是这么一件看似特别简单的事情,到了 CK 这里,可谓大有乾坤,当然,在我决定要写这篇文章的时候,这里面的弯弯绕绕已基本上被我理清楚了。
那么这篇文章,就想来跟你聊一聊关于 CK 在存储配置上的一些,跟其他数据库有所不同的地方。
0. 关于CK的存储规则
对于 CK 来说,如果你只有一个存储目录(一块磁盘),那好说,直接配置成默认存储就好,比如在主配置文件 config.xml 中这么写:
就能够满足 CK 对于数据的基础存储需求,其他乱八七糟一些跟存储相关的,更加复杂的概念和配置,你根本就不需要搭理。
但是,一旦你对它的数据存储有着更高,更多样的需求之后,你就必须要了解下面这几个概念了:
1. 存储策略(storage policy)
对于 CK 来说,可以有大于等于1个的存储策略,默认的存储策略叫 default,而且必须存在,且不可更改。
对于任何一个存储策略来说,可以配置多个「卷(volume)」,但大部分情况下,其实配置一个卷就够了,而每个卷下面,又可以配置多个存储路径(多块磁盘):
但是呢,这里有个我认为比较奇葩的意外,那就是对于这个必须存在的 default 存储策略,它却只能配置一个存储目录(一块磁盘)。
至于我是怎么知道的,其实官方文档并没有明确告知,我是根据以往经验,试错试出来的,这个后文会讲。
2. 卷(volume)
这个是存储策略的下一级,是一个逻辑的概念,每个存储策略可以包含多个卷,但是在我的经验里,绝大多数情况,用一个卷就够了,而一个卷,又可以配置多块磁盘。
比如这里的 volume01 包含 disk02 跟 disk03:
在数据写入的时候,配置了该卷对应的存储策略的表,会将数据并行写入到这2个目录中,提高IO效率。
3. 默认磁盘(default disk)
必须指定的数据存储目录,只能指定一个(一块磁盘),会存储所有表的元数据信息。此外,在建表的时候,除非特别设置,否则数据也全都会存储到个目录中。
4. 其他盘(disk)
必须要跟上面的默认盘分开,也必须隶属于除 default 存储策略之外的其他策略。
比如:
而且,从配置文件给出的配置案例来看,这个 disk 的类型相当之丰富,除了可以配置本地的磁盘目录外,还可以配置外部的文件系统,比如S3、HDFS等。
1. 测试验证
其实一开始的时候,我的想法非常朴素,不就是额外再加硬盘嘛,那我直接在原来配置的基础上,再把新的磁盘目录添上不就行了吗,毕竟之前的 ES 就是这么干的。
ES的多磁盘配置
虽然不知道符不符合配置规范,但,来都来了,那就试试呗。
于是,照猫画虎,为了防止意外发生,我新找了一台机器,根据这台机器的磁盘情况,在默认存储的位置,配了两个目录。
结果你猜怎么着,CK服务居然可以启动成功。
只不过,结果跟咱想的有点不太一样,CK并没有把这个配置当成两个目录,而是一个。
看得我哭笑不得,算了,不折腾了。
你说要是官网,或者配置文件里面的解释说明里,能顺带提那么一嘴,「就只允许配置一个单目录」,我也不至于干出这么让人尴尬的事情来不是。
那正确的玩法是什么样的呢?
来看一眼,我研究一番之后的配置,这里既配置了额外的2个本地磁盘目录,还添加了另外一个 hadoop 集群的HDFS存储路径。
<path>/hddata01/clickhouse/path>
<storage_configuration>
<disks>
<disk02>
<path>/hddata02/clickhouse/path>
disk02>
<disk03>
<path>/hddata03/clickhouse/path>
disk03>
<hdfs>
<type>hdfstype>
<endpoint>hdfs://xxxxx:8020/DATA/clickhouse/endpoint>
hdfs>
disks>
<policies>
<policy01>
<volumes>
<volume01>
<disk>disk02disk>
<disk>disk03disk>
volume01>
volumes>
policy01>
<policy02>
<volumes>
<volume01>
<disk>hdfsdisk>
volume01>
volumes>
policy02>
policies>
storage_configuration>
这个配置文件对应有2个存储策略,其存储策略、卷、磁盘的关系如下:
policy01关系图
policy02关系图
如此配置之后,CK服务就能正常启动起来。
服务启动之后,为了检验刚才配置是否生效,我们需要在命令行中,去查询一些相关的信息。
这里就要涉及到两张重要的「系统表」,一张叫: system.storage_policies ,另一张叫:system.disks (按理来说应该还有一张 system.volumes 的表才对,但是没有,不过不影响)。
查询当前 CK 包含有哪些存储策略:
可以看到,配置里新添加的额外2个存储策略已经能查到了。
再查询当前CK可用的磁盘情况。
2. 如何使用
CK 的这种存储机制,比较膈应的一点在于,它不像其他数据库那么“傻瓜式”,你配了几个目录,所有表的数据,就往几个目录里写,至于怎么写?轮休还是并发,由数据库自己来决定。
但是 CK 不一样,它应该是我目前为止接触的数据库中,把“手动挡”理念贯彻得最彻底的一个了。
建表时,如果你不额外指定「存储策略」,那么就使用的默认(default)存储策略,对应的数据也只会存储到 default 策略对应的目录上(且只能配一个)。
先随便建张表:
然后通过查询 system.tables 这张表,就可以知道当前创建的表,用的哪个存储策略,以及对应的目录。
往里写入几条数据后,再通过另一张表 system.parts 来查看数据在目录中的存储情况。
可以看到,数据只会存储到对应的1个目录中。
再不那么随便地建另一张表:
通过指定存储策略(policy01),创建另一张表之后,再用同样的方式,查询到当前表所使用的存储策略,以及对应的存储路径。
再次写入几条数据后,查询其数据在各个目录中的存储情况:
可以看到,数据会存储到对应的2个目录中。
所以,到这里,你应该能看出 CK 这个存储机制的缺点了,那就是:就算我的机器同时有3块数据盘,但是,你不能通过一次性配置,来达到让它们均匀存储数据的目的。
最后
虽然说,CK 的数据存储机制非常的丰富,且强大。但是呢,在我看来,它颠覆了以往我们对数据库多目录配置的使用习惯。
在便利性上,会多少让人有些不适,也进一步提高了使用者的门槛,需要时间去适应。
那么对于 CK 的这种多存储策略配置方式,你怎么看?