表分片和副本
本主题不适用于 ClickHouse Cloud:在 ClickHouse Cloud 中,Parallel Replicas 的作用类似于传统无共享架构 ClickHouse 集群中的多个分片,而对象存储则替代副本,以确保高可用性和容错能力。
ClickHouse 中的表分片是什么?
在传统的 无共享(shared-nothing) ClickHouse 集群中,当满足以下两种情况之一时会采用分片:① 数据量对单个服务器来说过大,② 单个服务器处理数据过慢。下图展示的是情形 ①: uk_price_paid_simple 表的数据量超过了单机的容量:

在这种情况下,可以将数据以表分片的形式拆分到多个 ClickHouse 服务器上:

每个 ^^分片(shard)^^ 持有数据的一个子集,并作为一个常规的 ClickHouse 表,可以被独立查询。不过,此类查询只会处理该子集;根据数据分布情况,这在某些场景下是可以接受的。通常,会使用一个分布式表(通常每台服务器一个)来提供整个数据集的统一视图。分布式表本身不存储数据,而是将 SELECT 查询转发到所有分片,汇总结果,并将 INSERT 请求路由到各分片以实现数据的均匀分布。
Distributed 表创建
为了演示 SELECT 查询转发和 INSERT 路由,我们以上文 What are table parts 中的示例表为例,该表被拆分为位于两台 ClickHouse 服务器上的两个分片。首先,我们给出在此基础上创建相应 ^^Distributed 表^^ 的 DDL 语句:
ON CLUSTER 子句会将该 DDL 语句变为分布式 DDL 语句,并指示 ClickHouse 在 test_cluster 的集群定义中列出的所有服务器上创建该表。分布式 DDL 需要在集群架构中额外部署一个 Keeper 组件。
对于Distributed 引擎的参数,我们需要指定 ^^集群^^ 名称(test_cluster)、分片目标表所在的数据库名(uk)、分片目标表的名称(uk_price_paid_simple),以及用于 INSERT 路由的 分片键(sharding key)。在本示例中,我们使用 rand 函数将行随机分配到各个分片。不过,依据具体使用场景,任何表达式——即使是复杂表达式——都可以用作分片键。下一节将演示 INSERT 路由的工作方式。
INSERT 路由
下图展示了在 ClickHouse 中,对 ^^分布式表^^ 执行 INSERT 时的处理过程:

① 将一条针对 ^^分布式表^^ 的 INSERT(本例中仅包含一行)发送到托管该表的 ClickHouse 服务器,可以直接发送,也可以通过负载均衡器转发。
② 对于 INSERT 中的每一行(本例中只有一行),ClickHouse 计算分片键(此处为 rand()),将结果对 ^^shard^^ 服务器的数量取模,并将其作为目标服务器 ID(ID 从 0 开始,依次递增)。然后将该行转发到对应服务器,并在该服务器上的表 ^^shard^^ 中③执行插入。
下一节将说明 SELECT 转发的工作方式。
SELECT 转发
下图展示了在 ClickHouse 中使用 ^^分布式表^^ 处理 SELECT 查询的过程:

① 指向 ^^分布式表^^ 的 SELECT 聚合查询被发送到相应的 ClickHouse 服务器,可以直接发送,也可以通过负载均衡器转发。
② ^^分布式表^^ 将查询转发到所有承载目标表分片的服务器,在这些服务器上,每个 ClickHouse 服务器会并行计算其本地聚合结果。
然后,由最初接收到该查询并承载目标 ^^分布式表^^ 的 ClickHouse 服务器 ③ 收集所有本地结果,④ 将其合并为最终的全局结果,并在 ⑤ 将其返回给查询发起方。
ClickHouse 中的表副本是什么?
ClickHouse 中的复制通过在多个服务器之间维护 ^^shard^^ 数据的副本 来确保数据完整性和故障切换。由于硬件故障不可避免,复制通过确保每个 ^^shard^^ 都有多个副本来防止数据丢失。写入可以直接发送到任意 ^^replica^^,也可以通过分布式表发送,由该分布式表为此次操作选择具体的 ^^replica^^。变更会自动传播到其他副本。在发生故障或维护时,数据仍可在其他副本上访问,而一旦故障主机恢复,它会自动完成同步以保持最新状态。
下图展示了一个包含六台服务器的 ClickHouse ^^cluster^^,其中前面介绍的两个表分片 Shard-1 和 Shard-2 各有三个副本。一个查询被发送到该 ^^cluster^^:

查询处理方式与无副本的部署类似,只是每个 ^^shard^^ 中仅有一个 ^^replica^^ 会执行该查询。
副本不仅确保数据完整性和故障切换,还通过允许在不同副本上并行运行多个查询来提升查询处理吞吐量。
① 目标为 ^^distributed table^^ 的查询被发送到相应的 ClickHouse 服务器,可以直接发送,或通过负载均衡器转发。
② ^^Distributed table^^ 将查询转发到每个 ^^shard^^ 的一个 ^^replica^^,每个托管被选中 ^^replica^^ 的 ClickHouse 服务器并行计算其本地查询结果。
其余处理与无副本部署时的流程相同,且未在上图中展示。托管最初被访问的 ^^distributed table^^ 的 ClickHouse 服务器会收集所有本地结果,将其合并为最终的全局结果,并将其返回给查询发起方。
请注意,ClickHouse 允许为步骤 ② 配置查询转发策略。默认情况下——与上图不同——如果本地 ^^replica^^ 可用,则 ^^distributed table^^ 会优先选择本地副本,但也可以使用其他负载均衡策略。
在哪里可以找到更多信息
如需在本高层概述之外进一步了解表分片和副本,请参阅我们的部署与扩展指南。
我们也强烈推荐观看以下教程视频,以更深入地了解 ClickHouse 的分片和副本: