背景
之前公司面临磁盘不足的问题,虽然通过增加磁盘来缓解了。但是clickhouse集群节点扩充是发展迟早要面临的问题,所以尝试思考解决方案。
ck不同于hadoop体系,hdfs当集群增减节点时可以通过balance命令去自动调节。但ck集群不能自动感知集群拓扑变化,也不能自动 balance 数据。当集群数据量较大,复制表和分布式表过多时、想做到表维度、或者集群之间的数据平衡会导致运维成本很高。
方案
这里提供三个解决思路
方式一、复制
当我们追求分布式表在新集群的平衡,数据量不大的情况,可以在新集群建立临时表B、然后将原始表A写入B中,再删除A表重新创建,之后将B表写入A中。
这种方式并不是数据量大、表数量过多的情形。
方式二、配置权重
当我们先用磁盘不够用的情况、通过配置权重指定大部分数据写入新的节点,随着时间流逝,原节点具有TTL的部分数据自动删除,数据会趋于均衡,最后调回原始权重。是一种比较可行的方案。只需要配置/etc/metrika.xml 中各个shard的权重即可。
<clickhouse_remote_servers>
<ck_cluster>
<shard>
<weight>99</weight>
<replica>
<host>dc-sit-225</host>
<port>9000</port>
<user>default</user>
<password></password>
</replica>
</shard>
<shard>
<weight>1</weight>
<replica>
<host>dc-sit-226</host>
<port>9000</port>
<user>default</user>
<password></password>
</replica>
</shard>
</ck_cluster>
</clickhouse_remote_servers>
列如我这里设置dc-sit-225节点权重为99,dc-sit-226节点权重为1。需要注意的是权重必须大于0(经过测试,小于0时节点会启动失败,等于0时配置不会生效)。
方式三、直接扩容不迁移数据
我们可以给每个节点中的表设置TTL保留时间,随着时间的进行,已经保留时间长的数据会逐渐的被清除掉。到最后,节点的数据会均很分布
- 优点:横向扩容,配置简单不需要额外操作,只需将每个节点的配置文件更新即可
- 缺点:要想达到数据均衡所需的时间较长,期间查询历史数据还是由原来节点合并完成,没有完全发挥分布式的优势
步骤
1、将配置文件进行拷贝到待安装节点
2、更改配置文件中的 metrika.xml 中关于 副本、分片的配置。例如:
(1)添加分片、副本
<clickhouse_remote_servers>
<report_shards_replicas>
<shard>
<weight>1</weight>
<!-- false代表一次性写入所有副本,true表示写入其中一个副本,配合zk来进行数据复制 -->
<internal_replication>true</internal_replication>
<replica>
<host>172.17.0.3</host>
<port>9000</port>
<user>default</user>
<password>default</password>
</replica>
</shard>
<shard>
<weight>1</weight>
<!-- false代表一次性写入所有副本,true表示写入其中一个副本,配合zk来进行数据复制 -->
<internal_replication>true</internal_replication>
<replica>
<host>172.17.0.4</host>
<port>9000</port>
<user>default</user>
<password>default</password>
</replica>
</shard>
<shard>
<weight>1</weight>
<!-- false代表一次性写入所有副本,true表示写入其中一个副本,配合zk来进行数据复制 -->
<internal_replication>true</internal_replication>
<replica>
<host>172.17.0.6</host>
<port>9000</port>
<user>default</user>
<password>default</password>
</replica>
</shard>
</report_shards_replicas>
</clickhouse_remote_servers>
(2)更改macros的参数
<!-- 配置参数:集群名,分片名,副本名 -->
<macros>
<layer>report_shards_replicas</layer>
<shard>01</shard>
<replica>cluster-01-1</replica>
</macros>
3、将以前表的结构拷贝到新增节点: (只需拷贝metadata目录下的文件即可)
mv metadata/ 到当前节点clickHouse的data目录下的
经过尝试,上面直接讲metadata的表结构拷贝过去的方法,有一个致命的BUG。如果表是分布式表,直接将表结构拷贝,虽然clickHouse中表已经创建成功,但是在ZK上的表的唯一地址并不会自动创建。所以所有需要与ZK交互的表都变成: Read Only模式,不能插入数据
改变思路:手动创建表结构
步骤:
- 1、不需要对每一个表来show create table获取表结构,我们复用metadata下的建表语句
- 2、通过代码来进行转换,将metadata的 *.sql 语句中所有的 ATTACH 替换成Create
metadata中的sql示例
ATTACH TABLE cs_user_info
(
`id` Int32,
`user_name` String,
`pass_word` String,
`phone` String,
`email` String,
`time` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/test/cs_user_info', '{replica}')
ORDER BY time
SETTINGS index_granularity = 8192
- 将转化的Sql语句集中保存至某一目录下,eg:/data/salt/clickHouse
- 通过CK的客户端来实现建表语句:
$file代表每个sql文件
sudo clickhouse-client -h 172.20.3.xxx --port 9000 -u admin --password 6Ml2IxJN --multiquery < $file
手动同步数据:
在新的服务器上创建相同的表,将需迁移的服务器上的表数据移动到新的服务器对应目录下,然后连接clickhouse执行以下语句:
detach table szt_data_t3; --先将表与数据分离(若表已存在)
attach table szt_data_t3; --然后重新添加进来