ClickHouse 中的所有MergeTree家族引擎前面加上Replicated就成了支持副本的合并树引擎.
本文以ReplicatedMergeTree引擎作为演示,其他副本合并树引擎是一个道理.
ReplicatedMergeTree如果有两个副本的话,相当于分布在两台clickhosue节点中的两个表,但是这个两个表具有协调功能,无论是哪个表执行insert或者alter操作,都会同步到另外一张表,这样子很好理解,副本就是相互同步数据的表.
复制合并树只有进行INSERT或者ALTER或者TRUNCATE操作才会同步,DROPATTACHDETACHRENAME只会作用于本地表(RENAME说明表名可以不同)

复制合并树引擎需要借助zookeeper实现数据的同步,所以要使用它就必须要先配置zookeeper.
zookeeper要求3.4.5以及以上版本,zookeeper的下载与安装Zookeeper的下载与安装 clickhouse两种配置zookeeper方式,一种是直接在config.xml中配置,另外一种是在外部文件中配置好了,在config.xml中进行引用.
1 内部配置方式:

vim /etc/clickhouse-server/config.xml

添加如下配置:

<zookeeper>
    <node index="1">  #index是连接zk的顺序
        <host>node01</host> #znode地址
        <port>2181</port>   #znode端口
    </node>
    <node index="2">
        <host>node02</host>
        <port>2181</port>
    </node>
    <node index="3">
        <host>node03</host>
        <port>2181</port>
    </node>

2 外部配置方式:
创建外部配置文件:

vim /etc/clickhouse-server/config.d/zks.xml
<?xml version="1.0"?>
<yandex>
   <zks>
     <node index="1">
            <host>node01</host>
            <port>2181</port>
     </node>
             <node index="2">
            <host>node02</host>
            <port>2181</port>
     </node>
             <node index="3">
            <host>node03</host>
            <port>2181</port>
     </node>
   </zks>
</yandex>

引入外部配置文件中的配置

vim /etc/clickhouse-server/config.xml
#文件的路径
<include_from>/etc/clickhouseserver/config.d/zks.xml</include_from>
#incl中指的是配置在外部配置文件中的标签
<zookeeper incl="zks" optional="true" />

上方是麻烦的写法,如果在zks中的标签<zks>...</zks>改为<zookeeper>..</zookeeper>,那么可以不要config.xml中的<zookeeper incl...>标签,只需要引用外部配置文件即可.

zk的配置不支持热更改,必须要重启clickhouse服务,但是在重启之前可以先使用以下sql查询:

select * from system.zookeeper where path = '/';

会报表不存在.
重启服务后,再还执行上方sql,就可以查询到zookeeper表,说明zookeeper配置好了.
Replicated建表语句:

ENGINE = ReplicatedMergeTree('/clickhouse/tables/shard/table_name', 'replica')

除了上方,其他部分与MergeTree建表语句无异.
zookeeper路径/clickhouse/tables/shard/table_name/clickhouse/tables为固定前缀(虽然可以不这样写,但是官网中建议这样做,所以我们就这样配置,减少不必要的麻烦)/shard需要自己配置shard(分片)名称,table_name指表的名称
replica代表副本的名称.
因为这里不做分片,所以我三台服务分别这样指定三个副本

(’/clickhouse/tables/01/table_name’, ‘node01’)
 (’/clickhouse/tables/01/table_name’, ‘node02’)
 (’/clickhouse/tables/01/table_name’, ‘node03’)


分别在三台服务上执行

create table replicatedTest(id Int16)
engine=ReplicatedMergeTree('/clickhouse/tables/01/replicatedTest','node01')
order by id;
create table replicatedTest(id Int16)
engine=ReplicatedMergeTree('/clickhouse/tables/01/replicatedTest','node02')
order by id;
create table replicatedTest(id Int16)
engine=ReplicatedMergeTree('/clickhouse/tables/01/replicatedTest','node03')
order by id;

创建好了以后在任意一台服务上执行:

insert into replicatedTest values(1);

之后三台分别查询,结果一致

select * from replicatedTest;
┌─id─┐
│  1 │
└────┘

需要注意的是,如果在同一台服务上面执行两次一样i的insert,第二次执行会被忽略掉,这是为了防止因为异常导致的重试让一次数据多次写入.

上方创建表语句很麻烦是不是,需要分别到不同的机器上面执行不同的创建表语句,其实可以通过宏变量的方式来创建.

('/clickhouse/tables/{shard_name}/table_name','{replica_name}')

上方的{shard_name}与{replica_name}是对宏变量shard_name和replica_name的引用,每台服务器的配置文件中分别配置好这两个宏变量,那么每台服务需要执行的sql语句就编程一致的了.
分别在三台服务器上的config.xml中添加配置

<macros>
     <shard_name>01</shard_name>
     <replica>node01</replica>
 </macros>
<macros>
     <shard_name>01</shard_name>
     <replica>node02</replica>
 </macros>
<macros>
     <shard_name>01</shard_name>
     <replica>node03</replica>
 </macros>

此配置支持热加载,所以不需要重启服务
之后每台服务上面都执行下面的sql语句就可以起到一样的效果:

create table replicatedTest1(id Int16)
engine=ReplicatedMergeTree('/clickhouse/tables/{shard_name}/replicatedTest1','{replica_name}')
order by id;

如果针对于其他的合并数引擎可能会有额外的参数,这里拿ReplacingMergeTree来说,它可以有一个选择保留版本的参数,对于ReplicatedReplacingMergeTree来说,额外的参数就添加在后面,如:

engine=ReplicatedMergeTree('/clickhouse/tables/{shard_name}/replicatedTest1','{replica_name}',**score**)

其他有额外参数的MergeTree引擎也是一样,将参数添加.replica参数后面