跳转到主要内容
跳转到主要内容
编辑此页面

PostgreSQL 和 ClickHouse 的比较

Postgres 与 ClickHouse:等效和不同的概念

来自 OLTP 系统且习惯于 ACID 事务的用户应注意,ClickHouse 在不完全提供这些事务的情况下做出了有意的妥协,以换取性能。如果理解得当,ClickHouse 语义可以提供高持久性保证和高写入吞吐量。我们在下面重点介绍一些关键概念,用户在从 Postgres 开始使用 ClickHouse 之前应该熟悉这些概念。

分片与副本

分片和副本是两种用于扩展超出单个 Postgres 实例的策略,当存储和/或计算成为性能瓶颈时使用。Postgres 中的分片涉及将大型数据库拆分为更小、更易于管理的部分,分布在多个节点上。但是,Postgres 本身不支持分片。相反,可以使用诸如 Citus 之类的扩展来实现分片,在 Citus 中,Postgres 成为能够水平扩展的分布式数据库。这种方法允许 Postgres 通过将负载分散到多台机器上来处理更高的事务率和更大的数据集。分片可以是基于行或基于模式的,以便为工作负载类型(例如事务性或分析性)提供灵活性。分片可能会在数据管理和查询执行方面引入显著的复杂性,因为它需要跨多台机器的协调和一致性保证。

与分片不同,副本是额外的 Postgres 实例,包含来自主节点的所有或部分数据。副本用于各种原因,包括增强的读取性能和 HA(高可用性)场景。物理复制是 Postgres 的原生功能,涉及将整个数据库或重要部分复制到另一台服务器,包括所有数据库、表和索引。这涉及通过 TCP/IP 将 WAL 段从主节点流式传输到副本。相比之下,逻辑复制是更高级别的抽象,它基于 INSERTUPDATEDELETE 操作流式传输更改。尽管相同的结果可能适用于物理复制,但在针对特定表和操作以及数据转换和支持不同 Postgres 版本方面,可以实现更大的灵活性。

相比之下,ClickHouse 分片和副本是与数据分发和冗余相关的两个关键概念。ClickHouse 副本可以被认为是类似于 Postgres 副本,尽管复制最终是一致的,没有主节点的概念。与 Postgres 不同,ClickHouse 本身支持分片。

分片是您的表数据的一部分。您始终至少有一个分片。如果单个服务器的容量不足以运行并行查询的所有分片,则可以使用跨多个服务器分片数据来分散负载。用户可以在不同服务器上手动为表创建分片并将数据直接插入到其中。或者,可以使用分布式表和分片键来定义数据路由到哪个分片。分片键可以是随机的,也可以是哈希函数的输出。重要的是,一个分片可以由多个副本组成。

副本是您的数据的副本。ClickHouse 始终至少有一个数据副本,因此副本的最小数量为一个。添加第二个数据副本可以提供容错能力,并可能提供额外的计算能力来处理更多查询(并行副本 也可用于分配单个查询的计算,从而降低延迟)。副本是通过 ReplicatedMergeTree 表引擎 实现的,该引擎使 ClickHouse 能够在不同服务器之间保持多个数据副本同步。复制是物理的:只有压缩的部分在节点之间传输,而不是查询。

总之,副本是数据的副本,提供冗余和可靠性(以及潜在的分布式处理),而分片是数据子集,允许分布式处理和负载均衡。

ClickHouse Cloud 使用存储在 S3 中的单个数据副本和多个计算副本。数据可用于每个副本节点,每个副本节点都有一个本地 SSD 缓存。这仅依赖于通过 ClickHouse Keeper 的元数据复制。

最终一致性

ClickHouse 使用 ClickHouse Keeper(C++ ZooKeeper 实现,也可以使用 ZooKeeper)来管理其内部复制机制,主要侧重于元数据存储并确保最终一致性。Keeper 用于为分布式环境中的每次插入分配唯一的序列号。这对于维护跨操作的顺序和一致性至关重要。此框架还处理后台操作,例如合并和 mutation,确保这些操作的工作是分布式的,同时保证它们在所有副本中以相同的顺序执行。除了元数据之外,Keeper 还充当复制的综合控制中心,包括跟踪存储数据部分的校验和,并充当副本之间的分布式通知系统。

ClickHouse 中的复制过程 (1) 在数据插入到任何副本时开始。此数据以其原始插入形式 (2) 写入磁盘以及其校验和。写入后,副本 (3) 尝试通过分配唯一的块号并记录新部分的详细信息,在 Keeper 中注册此新数据部分。其他副本在 (4) 检测到复制日志中的新条目后,(5) 通过内部 HTTP 协议下载相应的数据部分,并根据 ZooKeeper 中列出的校验和对其进行验证。这种方法确保所有副本最终都持有一致且最新的数据,尽管处理速度或潜在延迟有所不同。此外,该系统能够并发处理多个操作,优化数据管理流程,并允许系统可扩展性和针对硬件差异的鲁棒性。


NEEDS ALT

请注意,ClickHouse Cloud 使用 云优化的复制机制,该机制适用于其存储和计算架构的分离。通过将数据存储在共享对象存储中,数据自动可用于所有计算节点,而无需在节点之间物理复制数据。相反,Keeper 仅用于在计算节点之间共享元数据(哪些数据存在于对象存储中的哪个位置)。

与 ClickHouse 相比,PostgreSQL 采用不同的复制策略,主要使用流式复制,其中涉及主副本模型,数据从主节点持续流式传输到一个或多个副本节点。这种类型的复制确保了接近实时的​​一致性,并且是同步或异步的,使管理员可以控制可用性和一致性之间的平衡。与 ClickHouse 不同,PostgreSQL 依赖于带有逻辑复制和解码的 WAL(预写日志)来在节点之间流式传输数据对象和更改。PostgreSQL 中的这种方法更直接,但可能无法在高度分布式环境中提供与 ClickHouse 通过其复杂使用 Keeper 进行分布式操作协调和最终一致性所实现的相同级别的可扩展性和容错能力。

用户影响

在 ClickHouse 中,脏读的可能性——用户可以将数据写入一个副本,然后从另一个副本读取可能未复制的数据——源于其通过 Keeper 管理的最终一致性复制模型。此模型强调分布式系统中的性能和可扩展性,允许副本独立运行并异步同步。因此,新插入的数据可能不会立即在所有副本中可见,具体取决于复制延迟以及更改通过系统传播所需的时间。

相反,PostgreSQL 的流式复制模型通常可以通过采用同步复制选项来防止脏读,其中主节点等待至少一个副本确认收到数据,然后再提交事务。这确保一旦事务被提交,就可以保证数据在另一个副本中可用。如果主节点发生故障,副本将确保查询看到已提交的数据,从而保持更严格的一致性级别。

建议

ClickHouse 的新用户应该意识到这些差异,这些差异将在复制环境中显现出来。通常,最终一致性足以满足数十亿甚至数万亿数据点的分析需求——在这些数据点中,指标要么更稳定,要么估计就足够了,因为新数据以高速率持续插入。

如果需要提高读取的一致性,则有多种选项。这两种示例都需要增加复杂性或开销——降低查询性能,并使扩展 ClickHouse 更具挑战性。我们建议仅在绝对必要时才使用这些方法。

一致性路由

为了克服最终一致性的一些限制,用户可以确保客户端被路由到相同的副本。这在多个用户查询 ClickHouse 且结果在请求之间应该是确定性的情况下很有用。虽然结果可能会有所不同,但随着新数据的插入,应查询相同的副本,以确保一致的视图。

这可以通过多种方法来实现,具体取决于您的架构以及您使用的是 ClickHouse OSS 还是 ClickHouse Cloud。

ClickHouse Cloud

ClickHouse Cloud 使用存储在 S3 中的单个数据副本和多个计算副本。数据可用于每个副本节点,每个副本节点都有一个本地 SSD 缓存。因此,为了确保结果的一致性,用户只需确保一致性路由到同一节点。

与 ClickHouse Cloud 服务的节点通信通过代理进行。HTTP 和 Native 协议连接将在它们保持打开状态的期间路由到同一节点。对于大多数客户端的 HTTP 1.1 连接,这取决于 Keep-Alive 窗口。这可以在大多数客户端上配置,例如 Node Js。这也需要服务器端配置,该配置将高于客户端,并在 ClickHouse Cloud 中设置为 10 秒。

为了确保跨连接的一致性路由,例如,如果使用连接池或连接过期,用户可以确保使用相同的连接(对于 Native 更容易),或者请求公开粘性端点。这为集群中的每个节点提供了一组端点,从而允许客户端确保查询被确定性地路由。

请联系支持人员以获取粘性端点的访问权限。

ClickHouse OSS

在 OSS 中实现此行为取决于您的分片和副本拓扑,以及您是否使用 分布式表 进行查询。

当您只有一个分片和副本(由于 ClickHouse 垂直扩展而很常见)时,用户在客户端层选择节点并直接查询副本,确保这是确定性选择的。

虽然在没有分布式表的情况下可以使用具有多个分片和副本的拓扑,但这些高级部署通常具有自己的路由基础设施。因此,我们假设具有多个分片的部署正在使用分布式表(分布式表可以用于单分片部署,但通常是不必要的)。

在这种情况下,用户应确保基于属性(例如 session_iduser_id)执行一致的节点路由。应在 查询中设置 设置 prefer_localhost_replica=0load_balancing=in_order。这将确保首选分片的任何本地副本,否则首选配置中列出的副本 - 假设它们具有相同数量的错误 - 如果错误更高,则将发生随机选择的故障转移。load_balancing=nearest_hostname 也可以用作此确定性分片选择的替代方案。

创建分布式表时,用户将指定一个集群。此集群定义(在 config.xml 中指定)将列出分片(及其副本) - 从而允许用户控制从每个节点使用它们的顺序。使用此方法,用户可以确保选择是确定性的。

顺序一致性

在特殊情况下,用户可能需要顺序一致性。

数据库中的顺序一致性是指数据库上的操作看起来以某种顺序执行,并且此顺序在与数据库交互的所有进程中保持一致。这意味着每个操作看起来都在其调用和完成之间瞬间生效,并且存在一个所有进程都观察到的所有操作的单一、约定的顺序。

从用户的角度来看,这通常表现为需要将数据写入 ClickHouse,并在读取数据时,保证返回最新插入的行。这可以通过以下几种方式实现(按优先级顺序排列)

  1. 读/写到同一节点 - 如果您使用原生协议,或者使用 会话通过 HTTP 执行读/写操作,那么您应该连接到同一副本:在这种情况下,您直接从您写入的节点读取,那么您的读取将始终是一致的。
  2. 手动同步副本 - 如果您写入一个副本并从另一个副本读取,您可以在读取之前发出 SYSTEM SYNC REPLICA LIGHTWEIGHT
  3. 启用顺序一致性 - 通过查询设置 select_sequential_consistency = 1。在 OSS 中,还必须指定设置 insert_quorum = 'auto'

有关启用这些设置的更多详细信息,请参阅 此处

使用顺序一致性将给 ClickHouse Keeper 带来更大的负载。结果可能意味着更慢的插入和读取速度。SharedMergeTree(在 ClickHouse Cloud 中用作主要表引擎)顺序一致性 产生的开销更少,并且扩展性更好。OSS 用户应谨慎使用此方法并测量 Keeper 负载。

事务 (ACID) 支持

从 PostgreSQL 迁移的用户可能习惯于其对 ACID(原子性、一致性、隔离性、持久性)属性的强大支持,这使其成为事务性数据库的可靠选择。PostgreSQL 中的原子性确保每个事务都被视为一个单独的单元,要么完全成功,要么完全回滚,从而防止部分更新。一致性通过强制执行约束、触发器和规则来维护,这些约束、触发器和规则保证所有数据库事务都导致有效状态。PostgreSQL 支持从读取已提交到可序列化的隔离级别,从而可以对并发事务所做的更改的可见性进行微调控制。最后,持久性是通过预写日志 (WAL) 实现的,确保一旦事务被提交,即使发生系统故障,它仍然存在。

这些属性对于充当真理来源的 OLTP 数据库很常见。

虽然功能强大,但这带来固有的局限性,并使 PB 规模具有挑战性。ClickHouse 在这些属性上做出妥协,以便在保持高写入吞吐量的同时提供大规模的快速分析查询。

ClickHouse 在 有限的配置 下提供 ACID 属性 - 最简单的情况是使用带有单个分区的 MergeTree 表引擎的非复制实例。用户不应期望在这些情况之外获得这些属性,并确保这些不是必需的。

使用 ClickPipes(由 PeerDB 提供支持)复制或迁移 Postgres 数据

信息

PeerDB 现在已在 ClickHouse Cloud 中原生提供 - 通过我们新的 ClickPipe 连接器 实现闪电般快速的 Postgres 到 ClickHouse CDC - 现在处于私有预览版。请 在此处注册

PeerDB 使您能够无缝地将数据从 Postgres 复制到 ClickHouse。您可以将此工具用于

  1. 使用 CDC 进行持续复制,允许 Postgres 和 ClickHouse 共存——Postgres 用于 OLTP,ClickHouse 用于 OLAP;以及
  2. 从 Postgres 迁移到 ClickHouse。