ClickHouse 实时分析(六)- ClickHouse 数据副本详解
1. 数据副本简介
副本的目的主要是保障数据的高可用性,即使一台 ClickHouse 节点宕机,那么也可以从其他服务器获得相同的数据。目前只有MergeTree
系列里的表可以支持副本:
- ReplicatedMergeTree
- ReplicatedSummingMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
ClickHouse 的数据副本机制是表级别的,不是整个服务器级的,也就是说只针对表进行复制,一个数据库中可以同时包含复制表和非复制表。副本机制对于 select 查询是没有影响的,查询复制表和非复制表的速度是一样的。而写入数据时,ClickHouse 的集群没有主从之分,大家都是平等的。只不过配置了复制表后,Insert 以及 Alter 操作会同步到对应的副本机器中。对于复制表,每个 Insert 语句会往 Zookeeper 中写入十来条记录,相比非复制表,写 Zookeeper 会导致 Insert 语句的延迟时间略长。但是,在 ClickHouse 建议的每秒不超过一个 Insert 语句的执行频率下,这个延迟时间不会有太大的影响。
2. 副本写入流程
在这其中,其实还有很多的实现细节。数据副本需要经过网络传输,所以副本中写入数据是有延迟的。默认情况下,ClickHouse 对于 Insert 语句,只会等待一个副本写入成功后就会返回。如果有多个副本的情况下,ClickHouse 是有可能丢失数据的。写入数据时,ClickHouse 只保证单个数据块的写入是原子的,而不能保证所有的数据写入是原子的。一个数据块的大小可以根据max_insert_block_size=1048576
行进行分块。数据块写入时是会去重的,一个同样的 Insert 语句多次重复执行,数据库块只会执行一次。这是为了防止用户重复插入数据或者网络波动等原因造成的数据重发。这个去重机制只对应Replicated*MergeTree
系列的表引擎,普通的MergeTree
是不带这个去重功能的。
3. 副本配置步骤
ClickHouse 的集群搭建依赖 Zookeeper。如果没有配置 Zookeeper 的话,依然可以创建复制表,但是这些复制表都将变成只读。另外,官方建议,不要在 ClickHouse 所在的服务器上运行 Zookeeper。因为 Zookeeper 对数据延迟非常敏感,而 ClickHouse 可能会占用所有可用的系统资源。
另外需要注意的是,当前版本要求 Zookeeper 版本最低为3.4.5
。并且,官方对于 Zookeeper 的优化配置也提出了指导意见。具体如下:https://clickhouse.com/docs/zh/operations/tips。
配置数据副本,需要用到三台服务器,在原来 hadoop121 之上,增加了 hadoop122、hadoop123 两台机器,根据之前 hadoop121 的配置来即可,具体参见《ClickHouse实时分析(二)- ClickHouse的安装部署教程》。
服务器准备完成后,开始配置 ClickHouse。打开 ClickHouse 的配置文件/etc/clickhouse-server/config.xml
,指定 Zookeeper 集群地址:
1 | <zookeeper> |
在 hadoop122 和 hadoop123 上同步上面的操作,然后重启 ClickHouse 服务。
4. 副本效果演示
副本只能同步数据,不能同步表结构,所以我们需要在每台机器上自己手动建表。这里演示副本只在 hadoop121 和 hadoop122 两台服务器上操作。
hadoop121:
1 | create table t_order_rep |
hadoop122:
1 | create table t_order_rep |
参数解释: ReplicatedMergeTree 中,第一个参数是分片的 zk_path 一般按照/clickhouse/table/{shard}/{table_name}
的格式写,如果只有一个分片就写 01 即可;第二个参数是副本名称,相同的分片副本名称不能相同。
在 hadoop121 上执行 insert 语句:
1 | insert into t_order_rep values |
在 hadoop122 上执行 select,可以查询出结果,说明副本配置正确: