上一篇文章写过centos 7下clickhouse rpm包安装和基本的目录结构,这里主要介绍clickhouse高可用集群的部署方案,由于对于默认的分布式表的配置,每一个分片只有一份,这样若是挂掉一个节点,则查询分布式表的时候直接会报错,这个是基于clickhouse本身实现的多分片单副本集群,配置也比较简单,这里说的高可用是指,每一个分片具备2个或以上副本,当某个节点挂掉时,该节点分片仍能够由其余机器上的副本替代工做,因此这样实现的分布式集群能够在挂掉至少1个节点时机器正常运行,随着集群节点数量的增长,则集群挂掉2个节点或以上可提供服务的几率也越大,至少能避免单点故障问题,集群的稳定性也更高.node
clickhouse集群的理想方案是以下所示:sql
这里有3个集群,每一个集群n个节点,每一个节点的数据依靠zookeeper协调同步,好比cluster1提供服务,若是cluster1里面挂掉多台机器那么cluster2的副本能够切换过来提供服务,若是cluster2的分片再挂了,那么cluster3中的副本也能够提供服务,cluster1~3同时挂掉的几率就很是小了,因此集群的稳定性能够很是高,其中单个集群的节点个数n决定了clickhouse的性能,性能是能够线性扩展的,具体副本集群的个数根据机器资源配置.数据库
若是机器资源确实特别少,想每一个节点都用上提供服务的话,那么能够每一个节点存储两个以上的副本,即提供服务的分片和其余机器的副本,实现相互备份,可是clickhouse不支持单个节点多个分片的配置,咱们能够人为设置在每一个节点上启动两个实例来实现,设计图以下:centos
图画的很是简陋,可是能够看出来3个节点每一个节点的tcp 9000对外提供服务,9001提供副本,其中2提供1的备份,3提供2的备份,1提供3的备份,这样假设挂掉1个节点,集群也能够正常使用,可是挂掉2个几点,就不正常了,这样的话是机器越多越稳定一些.tcp
上面两种方案,官网上仍是推荐的第一种方案可用性最高,这里为了演示采用第二种方式配置,其实两种方式的配置是彻底同样的,第二种配置反而更繁琐一些,下面详细说一下配置的流程,软件包结构就采用上一篇文章打包好的.分布式
0. 高可用原理:zookeeper + ReplicatedMergeTree(复制表) + Distributed(分布式表)性能
1. 前提准备:全部节点防火墙关闭或者开放端口;hosts表和主机名必定要集群保持一致正确配置,由于zookeeper返回的是主机名,配置错误或不配置复制表时会失败.测试
clickhouse测试节点2个:192.168.0.107 clickhouse1, 192.168.0.108 clickhouse2spa
zookeeper测试节点1个:192.168.0.103 bigdata设计
配置方案:两个节点各配置两个clickhouse实例,相互备份.
clickhouse1: 实例1, 端口: tcp 9000, http 8123, 同步端口9009, 类型: 分片1, 副本1
clickhouse1: 实例2, 端口: tcp 9001, http 8124, 同步端口9010, 类型: 分片2, 副本2 (clickhouse2的副本)
clickhouse2: 实例1, 端口: tcp 9000, http 8123, 同步端口9009, 类型: 分片2, 副本1
clickhouse2: 实例2, 端口: tcp 9001, http 8124, 同步端口9010, 类型: 分片1, 副本2 (clickhouse1的副本)
2. 修改启动脚本和配置文件
首先将启动脚本复制一个出来,除了上一篇文章说的外,主要修改配置文件位置和pid文件位置,以下:
这里配置文件好比使用config1.xml,pid使用clickhouse-server-1.pid
而后进入到配置文件目录,将原有配置文件拷贝一份,这里是config1.xml,而后修改配置:
主要修改内容是:日志文件(和以前不要冲突)、http端口、tcp端口、副本同步端口(这个改完以后clickhouse按照当前实例的端口自动和其余实例同步)、数据文件和tmp目录、users.xml(这个若是都同样能够用同一个)、最后就是集群配置了,下面重点叙述:
集群配置默认为:<remote_servers incl="clickhouse_remote_servers" />
zookeeper默认为:<zookeeper incl="zookeeper-servers" optional="true" />
macros默认为:<macros incl="macros" optional="true" />
首先是集群分片的配置,这个配置全部节点的全部实例彻底保持一致:
<remote_servers> <distable> <shard> <!-- Optional. Shard weight when writing data. Default: 1. --> <weight>1</weight> <!-- Optional. Whether to write data to just one of the replicas. Default: false (write data to all replicas). --> <internal_replication>true</internal_replication> <replica> <host>192.168.0.107</host> <port>9000</port> </replica> <replica> <host>192.168.0.108</host> <port>9001</port> </replica> </shard> <shard> <weight>1</weight> <internal_replication>true</internal_replication> <replica> <host>192.168.0.108</host> <port>9000</port> </replica> <replica> <host>192.168.0.107</host> <port>9001</port> </replica> </shard> </distable> </remote_servers>
配置里面的<distable>是分布式标识标签,能够自定义,到最后建立分布式表的时候会用到;而后weight是分片权重,即写数据时有多大的几率落到此分片,由于这里全部分片权重相同全部都设置为1,而后是internal_replication,表示是否只将数据写入其中一个副本,默认为false,表示写入全部副本,在复制表的状况下可能会致使重复和不一致,因此这里必定要改成true,clickhouse分布式表只管写入一个副本,其他同步表的事情交给复制表和zookeeper来进行,而后是replica配置这个好理解,就是一个分片下的全部副本,这里副本的分布必定要手动设计好,保证相互备份,而后再次说明是全部的节点配置一致. 此部分配置严格按照官网配置,参考连接:https://clickhouse.yandex/docs/en/operations/table_engines/distributed/
而后是zookeeper配置,这个也是全部示例配置都同样:
<zookeeper> <node index="1"> <host>192.168.0.103</host> <port>2181</port> </node> </zookeeper>
这里zookeeper只有一个,若是多个的话继续往下写,就像官网上给出的同样,参考下图:
而后是复制标识的配置,也称为宏配置,这里惟一标识一个副本名称,每一个实例都要配置而且都是惟一的,这里配置以下:
clickhouse1 9000 分片1, 副本1:
<macros> <layer>01</layer> <shard>01</shard> <replica>cluster01-01-1</replica> </macros>
clickhouse1 9001 分片2, 副本2:
<macros> <layer>01</layer> <shard>02</shard> <replica>cluster01-02-2</replica> </macros>
clickhouse2 9000 分片2, 副本1:
<macros> <layer>01</layer> <shard>02</shard> <replica>cluster01-02-1</replica> </macros>
clickhouse2 9001 分片1, 副本2:
<macros> <layer>01</layer> <shard>01</shard> <replica>cluster01-01-2</replica> </macros>
由上面配置能够看到replica的分布规律,其中layer是双级分片设置,在Yandex公司的集群中用到,由于咱们这里是单集群因此这个值对咱们没有影响所有同样便可,这里是01;而后是shard表示分片编号;最后是replica是副本标识,这里使用了cluster{layer}-{shard}-{replica}的表示方式,好比cluster01-02-1表示cluster01集群的02分片下的1号副本,这样既很是直观的表示又惟一肯定副本. 副本的文档连接下面会给出.
3. 建立本地复制表和分布式表
全部实例配置完上面这些以后,分别执行启动命令启动,而后全部实例都执行下面语句建立数据库:
CREATE DATABASE monchickey;
而后对于全部实例分别建立对应的复制表,这里测试建立一个简单的表
clickhouse1 9000 实例:
CREATE TABLE monchickey.image_label ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-01/image_label','cluster01-01-1',insert_time, (label_id, insert_time), 8192)
clickhouse1 9001 实例:
CREATE TABLE monchickey.image_label ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-02/image_label','cluster01-02-2',insert_time, (label_id, insert_time), 8192)
clickhouse2 9000 实例:
CREATE TABLE monchickey.image_label ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-02/image_label','cluster01-02-1',insert_time, (label_id, insert_time), 8192)
clickhouse2 9001 实例:
CREATE TABLE monchickey.image_label ( label_id UInt32, label_name String, insert_time Date) ENGINE = ReplicatedMergeTree('/clickhouse/tables/01-01/image_label','cluster01-01-2',insert_time, (label_id, insert_time), 8192)
到这里复制表就建立完毕了,注意引号部分只能用单引号,其中核心的地方是同一个分片在zookeeper上面的znode相同,下面包含数据表的多个副本,当一个副本写入数据时会自动触发同步操做. 上面建表语句和配置文件对应着看应该容易理解,更详细的说明参考文档:https://clickhouse.yandex/docs/en/operations/table_engines/replication/ 文档关于ReplicatedMergeTree叙述以下:
而后建立完上面复制表以后,能够建立分布式表,分布式表只是做为一个查询引擎,自己不存储任何数据,查询时将sql发送到全部集群分片,而后进行进行处理和聚合后将结果返回给客户端,所以clickhouse限制聚合结果大小不能大于分布式表节点的内存,固然这个通常条件下都不会超过;分布式表能够全部实例都建立,也能够只在一部分实例建立,这个和业务代码中查询的示例一致,建议设置多个,当某个节点挂掉时能够查询其余节点上的表,分布式表的建表语句以下:
CREATE TABLE image_label_all AS image_label ENGINE = Distributed(distable, monchickey, image_label, rand())
分布式表通常用本地表加all来表示,这里distable就是上面xml配置中的标签名称,最后的rand()表示向分布式表插入数据时,将随机插入到副本,在生产环境建议插入的时候客户端能够随机分桶插入到本地表,查询的时候走分布式表,即分布式表只读,本地复制表只写.
配置好上面这些能够尝试经过不一样clickhouse实例写入数据测试,而后查询能够发现分片都会单独同步,不一样分片间数据互不影响,经过分布式表查询能够查询到全部的数据;若是停掉clickhouse2这个节点,此时clickhouse会自动切换为可用的副本使用,无需人工干预,如今查询分布式表仍然可用,当clickhouse2上面的实例启动恢复的时候,clickhouse会自动切换回来而且作数据的同步,这样就实现了高可用性.
上面就是clickhouse高可用集群的基本配置,确实如一些文章所说像一辆手动挡的车,用的越熟练越好用,另外关于性能和深刻的配置随着之后使用会继续分享,最后本人表达能力不是太好,若是文中有错误或叙述的不当,但愿路过的大牛们指出,很是感谢^_^