bigywater.tech
ClickHouse 内部原理 · 57

分片和副本:两个概念为什么不能混淆

真实查system.clusters看清楚shard_num和replica_num是两个独立维度,说明混淆分片和副本会导致对集群数据量的错误理解。

2个shard_num
真实数据被切成2份不重叠的子集
1个shard有2个replica
真实分片1的数据有2份冗余拷贝,分片2只有1份

做的事:真实查system.clusters,看清楚shard和replica是两个独立的维度

代码SELECT cluster, shard_num, replica_num, host_name, port FROM system.clusters WHERE cluster='mycluster';

验证:真实的拓扑,shard_num和replica_num是两个独立的编号

实测 · 本机执行输出
shard_num  replica_num  host        port
1          1            127.0.0.1   19110   ← node1,分片1的第1个副本
1          2            127.0.0.1   19120   ← node2,分片1的第2个副本
2          1            127.0.0.1   19130   ← node3,分片2的第1个副本

真实的拓扑是:shard_num只有1和2两个值——意味着数据被真实切成了两个不重叠的子集;replica_num在shard_num=1下有两个值(1和2)、shard_num=2下只有一个值——意味着分片1的数据真实保存了2份拷贝(在node1和node2上),分片2的数据真实只有1份拷贝(在node3上)。

混淆这两个概念,真实会导致查询结果算错

这组编号真实揭示了一条容易被混淆的规则:shard回答的问题是"这份数据被切成了几份互不重叠的子集",replica回答的问题是"每一份子集真实保存了几份互相冗余的拷贝"——两者是完全独立的两个维度,一个决定数据的切分方式,一个决定每一份切片的容灾/负载分摊能力。本系列上一篇《Distributed表》验证过的现象——3个本地表加起来150行、但集群真实只有100行不重复的数据——根源就是把"分片1有两个replica"误当成了"这两个节点各存了一半的分片1数据":如果真的这么理解,就会真实错误地把node1和node2的本地行数相加当成分片1的总量(50+50=100),实际上分片1的真实数据量就是50,node1和node2的50行是完全一样的,只是两份冗余拷贝而已。真实的正确心智模型是:先确定有多少个不重叠的分片(决定了数据被拆成几份,也决定了单次查询理论上能并行到多少个节点),再确定每个分片配几个副本(决定了这份数据能容忍几个节点同时故障、以及读请求能不能在多个节点间分摊)——本系列后面《Sharding Key》会验证数据具体怎么落到哪个分片,《ReplicatedMergeTree》会验证副本之间具体怎么同步数据,这两件事的机制完全不同,值得从概念上先分清楚。

分步演示:从system.clusters真实的编号看清两个概念

每一步都是本文上面用真实system.clusters跑出来的原始结果。

shard决定切分,replica决定冗余,真实是两个独立维度
这一步新验证的编号

    本文用到的工具

    • 本机真实的3节点ClickHouse集群,真实的 system.clusters(shard_num/replica_num)
    京ICP备2026067502号-1京公网安备11010502063487号