我们很高兴介绍 Synq 创始人 Petr Janda,他最近在 2023 年 5 月 25 日伦敦举行的 ClickHouse Meetup 上发表了演讲。在他的演讲中,Petr 深入探讨了使用 ClickHouse 构建面向用户和内部应用程序的过程。
现在,作为客座撰稿人,Petr 在这篇全面的博客文章中扩展了他的演讲内容。了解他的 Synq 团队如何使用 ClickHouse 构建统一数据平台,巧妙地融合了运营和分析需求。
数据驱动着每个软件系统。
其复杂性、多样性、急剧增加的体量以及苛刻的用例催生了专用数据系统的发展——一些专注于低延迟运营用例,另一些专注于跨大规模数据集的分析查询。因此,技术堆栈通常分为分析系统和运营系统,它们各自独立发展。
分析系统在过去十年中发展迅速——从 Hadoop 到 Redshift 等云产品,再到后来的 Snowflake 或 BigQuery。但是,尽管它们能够弹性扩展和处理几乎无限量的数据(只要您有足够的资金支付账单),但它们并非为具有低延迟要求的典型运营用例而设计。
但情况必须如此吗?如果我们围绕统一数据平台构建运营和分析用例,我们的系统会是什么样子?
当我们一年前创办 Synq 时,我们认真思考了这些问题。快进到今天,我们使用单一数据平台 ClickHouse 为我们整个面向用户的应用程序、内部分析、数据可靠性监控警报、应用程序内分析以及持续数据流上训练的机器学习模型提供支持。
找到合适的平台
Synq 是一个数据可观测性平台,用于分析来自复杂数据生态系统的日志级别数据。其核心是一个大型日志处理引擎,可摄取和处理来自数十个系统的数据。数据以连续事件流的形式到达,当我们的客户运行大型批处理作业时,或者当我们在几分钟内为新加入的客户回填数据时,数据量会频繁突增。
我们确定了选择工具的三个关键标准
- 为了提供卓越的用户体验,我们为回填数据设定了雄心勃勃的性能目标:我们希望在客户加入我们的产品后立即为其提供价值。可扩展的摄取性能可以轻松处理每秒数万次操作,这一点至关重要。我们希望达到从外部系统提取数据的速度限制,而不是受到内部存储速度的限制。
- 我们希望基础设施能够满足我们最初定义的一组用例,并提供快速支持新用例的功能。理想的平台将使我们能够创建原始日志级别数据的各种转换,从而可以有效地查询这些数据。
- 最后,我们有一个雄心壮志,即构建一个单一平台,该平台可以存储我们的原始日志数据,同时充当我们应用程序和 API 所需的大多数数据用例的服务层,从而减少围绕专门存储系统进行 ETL 数据的需求。我们为应用程序性能设定了雄心勃勃的目标,因此需要一个底层数据平台来舒适地为我们的最终用户应用程序提供亚秒级延迟(低至数百毫秒)。
我们对弹性摄取性能、灵活的内部转换以及对低延迟查询的支持有苛刻的组合要求。
当我们开始构建系统的核心时,我们从带有时间序列插件的 Postgres 开始。它足以支持我们的初步开发,但我们知道我们会超越它。在看到大型回填作业的次优性能后,我们决定寻找新平台。在对各种平台(包括领先的数据仓库提供商)进行测试后,我们经常可以满足上述三个要求中的两个,但只能满足部分三个要求。
直到我们找到了 ClickHouse。
我们花了几天时间进行测试才意识到这是一个完美的匹配。即使使用小型集群,我们也可以每秒摄取数万行;我们很快就使用了 ClickHouse 物化视图来创建特定于查询的数据模型,并看到数百毫秒的查询延迟,这满足了所有三个要求。在我们所有的测试中,ClickHouse 在高摄取负载下保持了一致的读取查询性能。
为了让我们的整个开发团队专注于我们平台的研发,我们与 ClickHouse Cloud 合作。从一开始,我们就对稳定性印象深刻。即使在巨大的压力下,我们的 ClickHouse 平台始终可靠地为应用程序查询提供服务。
构建基础
第一个挑战是构建可靠的摄取。我们的系统是用 Go 编写的,我们选择了官方维护的 Go 客户端 clickhouse-go。我们的摄取微服务从持久队列中消费数据,并在数据到达时将其推送到 ClickHouse。我们很快意识到,如果没有额外的处理,这是一种幼稚的方法。我们的系统会频繁插入数千个请求,但只有少量行,这对于将数据摄取到 ClickHouse 来说并不是最佳的。因此,我们看到表中的部分数量呈爆炸式增长,因为 ClickHouse 引擎无法足够快地合并它们。集群开始通过使我们的插入超时来保护自己。
我们必须改进我们的方法。
由于流量可能会激增,我们希望避免在我们的系统中缓冲任何事件。这会在重负载下导致巨大的内存峰值和潜在的 OOM 错误,因此在应用程序代码中进行缓冲不是一个选项。
最初,我们尝试利用 ClickHouse Buffered 表引擎。集群内着陆表前面的内存缓冲区解决了小部分问题。缺点是它会在我们的集群中分配大量内存。
在与 ClickHouse 团队协商后,我们最终确定了最终方法——异步插入。异步 API 无需缓冲表即可工作。从客户端的角度来看,缓冲机制是透明的,完全由 ClickHouse 管理。
小插入在集群上分组,并在插入达到一定总行数或每隔几秒钟刷新到表中。
此外,如果插入失败,我们不会确认队列中的消息,这将最终重试,使我们的系统能够抵御 ClickHouse 摄取中潜在的故障模式。
但这给我们留下了一个更大的挑战。
由于可能重复部分成功的插入,或者因为我们的队列不保证精确一次交付,我们需要处理重复事件。
作为解决方案,我们利用 ReplacingMergeTree 表引擎,该引擎在表部分合并时修剪重复项,并在我们的查询中进一步添加 LIMIT 1 BY 子句,以使用日志记录的代理键来解决合并操作删除之前表中存在的重复记录,合并操作在后台异步发生。
随着可靠且可扩展的摄取就位,我们可以利用集群的另一个关键组件:物化视图。
优化性能
我们的应用程序围绕小型且可组合的 API 调用而设计,这为我们在通用基础设施之上构建新体验提供了很大的灵活性,而无需不断更改 API。其中许多都在访问 ClickHouse。
微服务从 pubsub 消费数据,并将其流式传输到 ClickHouse 的表中,物化视图提供支持,物化视图创建专门的数据表,为低延迟 API 提供支持。
为了最大限度地提高性能,我们创建了专门的表,这些表将我们的原始日志数据转换为针对我们的查询优化的格式,并由适当的分区和排序键支持,以优化数据在磁盘上的布局。
我们了解到,为与我们的查询模式对齐的表选择合适的 ORDER BY 子句对于最大限度地减少每个查询扫描的数据量至关重要。在基于物化视图支持的预计算表上适当设置 ORDER BY 子句后,我们可以将即使是复杂的分析查询也微调到 <100 毫秒的延迟。
这些低级数据布局优化对于 ClickHouse 查询性能至关重要,因为通过调整布局,我们看到必须扫描以响应查询的数据量下降了一个数量级。这些表的延迟通常在 100 毫秒左右。
原始日志和专用表之间的数据通过物化视图实时保持同步。借助物化视图的灵活性和低级表控件,性能优化测试成本低廉。我们可以更快地进行更多测试,并最终找到优化的解决方案。
使用 dbt 的数据仓库用例
随着我们加入更多客户并扩展我们从中收集数据的第三方系统,我们注意到了数据中的新错误。
由于源工具中的错误配置或各种事件,我们已经看到更多客户系统并非总是提供 100% 准确的输入数据的情况。我们已经确定需要加强对我们代表客户摄取的数据的完整性、及时性和正确性的测试。
我们决定使用流行的数据转换框架 dbt 并创建审计表,这些表提取有关我们日志数据的摘要统计信息。
随着 dbt 的添加,我们改变了 ClickHouse 的使用模式。我们使用从其他表创建为 SELECT 语句的表来补充实时表同步,这感觉更接近传统的数据仓库。通过在不同时间间隔协调 dbt 执行,我们还可以将 ClickHouse 用于内部 BI 用例。我们发现这种设置非常实用,因为我们可以灵活地创建客户数据的新分析视图,而无需将其从我们的生产运营系统中移出。
应用内分析
由于所有客户数据都集中在一个位置,因此使用我们的 ClickHouse 集群作为许多其他用例的支柱是理所当然的。我们的客户希望在更高层次上了解他们的系统如何工作。他们希望分析模型的正常运行时间以及错误频率,以推断对数据质量的投资。或者了解其模型的速度和成本,以最大限度地提高其数据基础设施美元投资的价值。
所有必要的可观测性、运行时和质量指标都可以从我们的日志数据中计算出来。这也是 ClickHouse 和 dbt 组合的完美用例。
为了支持我们的分析视图,我们确定了一个包含十几个表的设计,每个表都预先计算了一组特定用例的指标,并具有预定义的最小时间粒度来细分数据。我们的客户通常希望按月分析指标趋势。我们已决定将数据聚合到天,以显示月度间趋势。
我们组合了几层逻辑:我们添加了额外的物化视图,以从原始日志中的 JSON 对象中解析出元数据。提取原始数据后,我们将日志级别事件聚合到每日存储桶中,从而大幅减小表的大小。每个 UI 查询都需要数千行紧密地位于底层存储中。这是由于我们使用表 ORDER KEY 完成的优化。典型的查询必须从磁盘扫描非常少量的数据。我们在 API 端点级别持续观察到约 ~100 毫秒的延迟,其中每个 API 调用至少查询五个不同的指标,这些指标是整个 UI 的一部分,并且非常流畅。
我们的应用内分析与任何其他应用程序部分一样快,这主要归功于优化的 ClickHouse 表。
结论
在我们使用 ClickHouse 的旅程中,不到一年就取得了很大的成就。我们的 ClickHouse 集群需要调整,但这也是它的强大之处。
凭借控制底层存储引擎、摄取机制或查询设置的能力,我们对存储具有极强的控制力,到目前为止,存储能够处理我们想到的任何用例,其性能可以支持交互式用户体验。物化视图和与 dbt 的集成为我们提供了很大的灵活性,可以快速开发新的数据用例,而无需任何额外的 ETL 代码或大型迁移。针对新用例优化的表可以使用 DDL SQL 创建,并使用单个 SELECT 语句回填。这使得开发非常高效。
ClickHouse Cloud 作为一个数据平台,支持内部分析、面向用户的分析和整个面向客户的应用程序。
在概念层面上,我们已经完全合并了我们的运营和分析存储。我们可以从用例的角度来考虑我们的系统,因为我们知道我们拥有一个高性能的数据平台和其他必要的构建块来支持它们。
我很高兴看到构建现代云系统的这种思维方式,其中分析和运营完全集成,尤其是在数据在几乎每个业务中都变得越来越重要的背景下。分析数据正在成为业务关键流程的一部分,并且从与运营系统保持紧密联系中获益匪浅。像 ClickHouse 这样的存储系统使构建此类系统成为可能。
关于 Synq
Synq 是一个数据可观测性平台,可帮助 Typeform、Instabee 和 LendInvest 等公司的团队监控其云数据堆栈。它构建在 ClickHouse 之上,可深入集成到 ClickHouse 集群中,并具有检测延迟数据加载和发现隐藏数据异常的功能,并辅以自动创建的数据沿袭和用于管理数据质量的工具。
Synq 检测到的数据异常示例,其中由于上游系统中的故障,表中的数据量开始异常增长。
通过解析来自 ClickHouse 的表、视图和物化视图的 SQL 定义提取的数据沿袭示例,概述 ClickHouse 集群内的数据流结构。
更多详情
- 本次演讲在 伦敦 ClickHouse Meetup 上进行,时间为 2023 年 5 月 25 日
- 演示文稿材料可在 GitHub 上获取
- 了解更多:https://www.synq.io/