clickhouse 数据复制方案

2,122 阅读3分钟

clickhouse 通常有两种比较常用的数据复制方案来做数据的备份

1.基于cluster+Distributed的复制方案

2.基于Zookeeper+ReplicatedMergeTree的复制方案

下面详细介绍一下两种复制方案的配置、原理及优缺点,数据库架构基于下图

image.png

从数据层面上来区分,1A 和 2A数据完全不同,1A和2A互为分片;1A和1B数据完全相同,1A和1B互为副本;

副本的目的是防止数据丢失增加数据安全;分片的目的是实现数据水平切分,加速查询。

1.基于cluster+Distributed的复制方案

--物理表DDL建表语句
create table if not exists eos_appstatistics.tb_mytest on cluster eos_ck_cluster
(
    id String,
    code String
)
engine = MergeTree ORDER BY id
SETTINGS index_granularity = 8192;
--分布式表DDL建表语句
create table eos_appstatistics.tb_mytest_dist on cluster eos_ck_cluster
(
    id   String,
    code String
)
 engine = Distributed('eos_ck_cluster', 'eos_appstatistics', 'tb_mytest', rand());

集群配置文件如下

<!-- 集群配置 -->
<clickhouse_remote_servers>
    <eos_ck_cluster>
        <!-- 数据分片1  -->
        <shard>
            <internal_replication>true</internal_replication>
            <replica>
                <host>server01</host>
                <port>9000</port>
                <user>default</user>
                <password></password>
            </replica>
            <replica>
                <host>server02</host>
                <port>9000</port>
                <user>default</user>
                <password></password>
            </replica>
        </shard>
        <!-- 数据分片2  -->
        <shard>
            <internal_replication>true</internal_replication>
            <replica>
                <host>server03</host>
                <port>9000</port>
                <user>default</user>
                <password></password>
            </replica>
            <replica>
                <host>server04</host>
                <port>9000</port>
                <user>default</user>
                <password></password>
            </replica>
        </shard>
    </eos_ck_cluster>
</clickhouse_remote_servers>

要注意<internal_replication>true</internal_replication>这个配置

image.png

经测试,想要基于分布式表进行数据复制,<internal_replication>必须设置为false;

在对分布式表进行写入的时候,会自动写入分布式表对应的两张子表中。

这样的数据复制方式被官方称为poor man's replication,需要自行处理存量数据、数据迁移等工作,官方不太建议使用。

2.基于Zookeeper+ReplicatedMergeTree的复制方案

集群配置文件中增加zookeeper的配置

<!-- ZK  -->
<zookeeper-servers>
  <node index="1">
    <host>10.**.**.**</host>
    <port>2181</port>
  </node>
  <node index="2">
    <host>10.**.**.**</host>
    <port>2182</port>
  </node>
  <node index="3">
    <host>10.**.**.**</host>
    <port>2183</port>
  </node>
</zookeeper-servers>

建表语句

--物理表DDL建表语句
create table eos_appstatistics.tb_test on cluster eos_ck_cluster
(
    id   String,
    code String
)
--{shard}同一分片下相同,{replica}必须保证唯一
 engine = ReplicatedMergeTree('/clickhouse/tables/{shard}/eos_appstatistics/tb_test', '{replica}')
 ORDER BY id
 SETTINGS index_granularity = 8192;
--分布式表DDL建表语句
create table eos_appstatistics.tb_test_dist on cluster eos_ck_cluster
(
    id   String,
    code String
)
 engine = Distributed('eos_ck_cluster', 'eos_appstatistics', 'tb_test', rand());
 
 
 ReplicatedMergeTree为复制表引擎

ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/table_name', '{replica}')

此句为官方给的例子,括号中的参数为zk的路径

{layer}指代的是第几层,同一层数据一样,可忽略不用

{shard}指的是分片编号,同一层的同一分片,数据互相复制

table_name 推荐和物理表名一致,方便分辨

{replica}指的是副本名称,必须保证在同一分片下唯一

其它要注意的配置

<!--此处必须设置为true-->
<internal_replication>true</internal_replication> 

<!--集群配置中节点的用户必须有相应的权限,在user.xml配置文件中-->
 <access_management>1</access_management>

<!--clickhouse docker启动时指定的hostname要与 集群配置文件中的host一致-->

此时可以直接往物理表插入数据,其副本会自动同步数据;

也可以直接往分布式表插入数据,即只写一个shard里面的一个副本,副本之间会自动同步数据。

该方案使用的是基于复制表ReplicatedMergeTree+Zookeeper的协调一致性完成数据的复制和数据一致性,副本之间的数据相互复制且会进行数据验证,自动保证数据一致性,这样的方案强依赖zookeeper,由于对zk的使用经验较少,先在测试环境观察一段时间可靠性。

3.总结

基于ClickHouse的集群的常见方案,结合业界的架构方案,优质的选择是基于ReplicatedMergeTree + Distributed的集群架构方案,也是分布式高可用的集群架构方案,在使用该集群架构的过程中,需要注意:

写表的方式:写本地表,读分布式表

由于分布式表的逻辑简单,仅仅是转发请求,所以在转发安全性上,会有风险,并且rand的方式,可能会造成不均衡,业界建议,通过LB轮询,写本地表,这样最保险和均衡。

此处我采用的是在clickhouse集群外加了一层nginx做负载均衡,写本地表,读分布式表(各个节点都创建分布式表)