
本文字数:4540;估计阅读时间:12 分钟

Meetup活动
ClickHouse Shanghai User Group第1届 Meetup火热报名中,详见文末海报!

本周,我们欢迎来自 Lago 的一篇博客文章,介绍了他们如何使用 ClickHouse 扩展一个事件引擎,并在此过程中将查询速度最高提高了 137 倍!这篇博客文章的原始版本发布在 Github 上。 【https://github.com/getlago/lago/wiki/Using-Clickhouse-to-scale-an-events-engine】

像许多公司一样,我们在扩展核心产品 Lago (一个开源的基于使用量计费平台)时,不得不在过程中更换数据库堆栈。随着我们逐渐受到欢迎,我们每分钟开始接收数百万个事件。我们初期使用的仅 Postgres 的简单堆栈已经无法满足需求。我们遭遇了严重的加载时间问题,影响了整个应用的性能。
经过一些探索,我们决定使用一个分布式的 ClickHouse 实例专门处理我们的流事件。我们的分析服务现在可以直接查询这个 OLAP 数据库 ClickHouse。对于所有其他数据需求,我们保留了 Postgres。
这个策略非常成功。自重构后,我们从未回头。
今天,我们将探讨这个混合数据库堆栈的决策,特别是为什么我们选择 ClickHouse。

大多数开发者,包括初级开发者,都有使用 OLTP (在线事务处理)数据库(如 Postgres)的经验。顾名思义,OLTP 数据库专为处理事务而设计。事务是一个独立的工作单元,可能包括以下操作:(i) 读取,(ii) 插入,(iii) 更新,和 (iv) 删除。
OLTP 数据库通常是通用数据库。由于它们支持各种类型的数据处理,可以在一定程度上解决任何数据问题。即使在大规模使用时,OLTP 数据库对于需要以下功能的软件来说也是非常出色的:
原子性事务,其中一组事务要么全部发生,要么根本不发生
一致性,其中写入和更新之间的查询是确定的和可预测的
对于大多数问题,这些都是重要的特征。对于一些问题,它们是绝对关键的。例如,银行应用程序在账户之间转账时不能有任何差错。对于这些问题,需要 OLTP 数据库来实现精确到分的准确性。
今天,我们仍然使用 Postgres 作为我们的主数据库,通过我们的 database.yml 文件进行配置。鉴于我们使用 Ruby on Rails,我们的 Postgres 模式由 Rails 的 Active Record 自动生成,这是一个 ORM,管理着我们各种模型,如费用、信用票据、发票、邀请、费用、优惠券等等。我们编写了一些自定义查询(考虑到 ORM 的性能限制),但在大多数事务中主要依赖 Active Record。
那么 OLAP (在线分析处理)数据库(如 ClickHouse)在哪里派上用场呢?Postgres 被设计为严格的原子性和一致性,这两个属性要求在任何查询处理之前,数据必须完全摄取。这对每分钟插入数百万行数据的表(例如,可计费事件,特别是那些基础设施服务如托管服务器的事件)造成了问题。具体来说,问题不在于插入数据,而在于同时处理复杂的分析查询而不锁定队列。这些数据汇总问题正是 OLAP 数据库(如 ClickHouse)大显身手的领域。
OLAP 数据库设计用于解决两个主要问题:(i) 以近似准确性高效回答复杂的读取查询和 (ii) 批处理大量写入查询。然而,OLAP 数据库历史上不擅长变更数据(通常需要重写整个数据库)或删除数据。
不同的 OLAP 解决方案(例如 ClickHouse、QuestDB、Druid)各有其优势。在下一节中,我们将深入探讨使 ClickHouse 成为最佳解决方案的具体特性。但所有 OLAP 解决方案都有一个共同特点——数据相对于像 Postgres 这样的 OLTP 数据库是以倒置布局存储的。

从用户的角度来看,表格的列和行仍然只是列和行。但在内存和磁盘上,数据是按列而不是按行进行扫描的。这使得聚合操作(例如将某个字段中的所有值相加)非常快,因为相关数据是顺序读取的。

ClickHouse 于 2016 年开源,如今在 AWS 和 GCP 上作为无服务器云服务提供。它是采用最广泛的 OLAP 数据库之一。
ClickHouse 有三个显著特点,使其成为满足我们需求的强大分析工具:(i) 动态物化视图,(ii) 专用引擎,和 (iii) 向量化查询执行。
总结如下:
动态物化视图。物化视图是从基础表中的原始数据生成的可查询视图。虽然许多数据库都支持物化视图,包括 Postgres,但 ClickHouse 的物化视图是一种特殊的触发器,当数据插入时执行查询。查询结果然后被分派到目标表,在那里合并和更新。这使得工作从查询时间转移到插入时间:因为目标表通常更小,查询结果更简单。这与普通的物化视图不同,普通物化视图只是特定时间点的快照,刷新代价非常高(这些在 ClickHouse 中也得到支持,称为“可刷新的物化视图”)。
专用引擎。许多数据库使用单一引擎来利用硬件处理查询/事务。然而,ClickHouse 有专用引擎用于数学函数,例如求和或平均数。
向量化查询执行。ClickHouse 的专用引擎利用向量化查询执行,硬件通过多个单元并行处理来实现共同结果(称为 SIMD——单指令多数据)。
结合其列式存储,这些特性使 ClickHouse 能够轻松地对数据库值进行求和、平均和聚合。
需要注意的是,Postgres 并非完全不能实现类似的结果,但这只能通过大量优化来实现。例如,有一个为 Postgres 设计的第三方向量化执行器,模仿 ClickHouse 的原生特性。还有一个快速刷新模块,使用 Postgres 的日志来动态更新物化视图。结合 Postgres 触发器,开发者可以创建一个类似 ClickHouse 的环境。但所有这些技术都需要大量设置工作和额外列,才能达到与 ClickHouse 相当的效率。

来自我为 PostHog 编写的 Postgres 与 ClickHouse 指南中的相关表情包
当然,将分析过程迁移到 ClickHouse 只是战斗的一半。接下来是将 ClickHouse 实际部署到生产环境中,可以采用几种策略。

在讨论我们的 ClickHouse 实现时,主要涉及两个不同的主题:(i) 我们使用 ClickHouse 的用途,以及 (ii) 我们的 ClickHouse 实例如何部署和维护。
我们在 ClickHouse 中查询什么
我们的 ClickHouse 实例接收由用户派发的原始可计费事件。虽然我们不自行编写 ClickHouse 模式(因为它是由 Active Record 自动生成的),但它被写入一个文件,该文件在我们的开源库中可用。我们的 ClickHouse 实例只有两个表——raw_events 和 raw_events_queue——以及一个物化视图 events_raw_mv。仅此而已。我们不在 ClickHouse 中存储任何不需要用于分析查询的“业务关键”数据。

具体而言,我们的 raw_events_queue 表使用 Kafka 表引擎从 Apache Kafka(一种开源事件流软件)读取行。events_raw_mv 在 raw_events_queue 表接收插入时被触发,将事件的元数据从 JSON blob 映射到字符串数组,并将这些数据推送到 raw_events 表。这是一个为大量写入设计的 MergeTree 表。raw_events 是 Lago 的一般代码库通过我们的 ClickHouseStores 类与之交互的表,在聚合可计费指标时调用它。raw_events 使用一个由 organization_id、external_subscription_id 和 code 组成的元组——加上一个时间戳——作为主键;鉴于 ClickHouse 对主键元组的复杂支持,这使得 ClickHouse 能够非常快速地定位行数据。

由于 ClickHouse 是一个开源数据库,可以在任何普通的 Linux 服务器上进行自托管。然而,许多公司更信赖托管数据库解决方案,因为它们 (i) 通常可以降低总体成本,(ii) 使数据库更容易扩展,以及 (iii) 负责安全的复制和备份。
目前,我们使用 ClickHouse Cloud,这是一种由 ClickHouse Inc. 提供的托管解决方案,部署了一个无服务器的 ClickHouse 实例,具有解耦的计算和存储功能。ClickHouse Cloud 使我们更容易扩展,而无需担心扩展带来的问题。

我们对比了 Postgres 和 ClickHouse 在几个关键聚合操作上的性能:
加权求和聚合
Postgres: 6.6秒

Clickhouse: 48毫秒

计数和求和操作
Postgres: 6.5秒

Clickhouse: 350毫秒

如图所示,迁移到 ClickHouse 后,我们的主要查询性能至少提高了 18 倍,最高可达 137 倍!

我们并不是唯一使用 ClickHouse 的开源项目。事实上,我们甚至不是唯一一个从 Postgres 迁移到 ClickHouse 的开源项目。另一个著名的例子是 PostHog,一个开源分析套件,由于每秒处理大量网络事件而从 Postgres 切换到 ClickHouse。
另一个典型的例子是 GitLab,它在其可观测性套件中使用 ClickHouse 存储流事件的数据。一般来说,当开源公司(和闭源项目)开始扩展时,通常会发现通用数据库如 Postgres 或 MySQL 不太适合。
即使是一些闭源解决方案,如 HTTP 数据流产品 Tinybird,也对 ClickHouse 做出了开源贡献,因为它们依赖于 ClickHouse。慢慢地,ClickHouse 在 OLAP 领域取得了与 Postgres 在 OLTP 领域相同的成功。

由于倒置表布局的硬件优化,随着应用程序的扩展,没有一种数据库可以满足所有需求。在我们的旅程中,由于产品的事件密集特性,我们相当早就遇到了这个问题。然而,这并不意味着每个团队都需要从 OLTP + OLAP 堆栈开始——只需在时机到来时准备好。

最近 ClickHouse 官方首次推出了 ClickHouse 认证开发人员(点击查看详情)的考试。提升您的职业生涯至行业顶尖水平!报名参加我们的官方 ClickHouse 认证考试,证明您的 ClickHouse 专业技能。
提示:我们正在开通国内购买渠道,请大家积极填写认证考试意愿到场问卷,敬请期待

好消息:ClickHouse Shanghai User Group第1届 Meetup 已经开放报名了,将于2024年7月20日在上海市徐汇区龙耀路8号阿里巴巴徐汇滨江园区X6-304 梅溪书院举行,扫码免费报名


征稿启示
面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com






