我们很高兴介绍 Synq 的创始人 Petr Janda,他最近于 2023 年 5 月 25 日在伦敦 ClickHouse 会议上发表了演讲。在演讲中,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 的缓冲表引擎。集群中目标表前的内存缓冲区解决了小部分问题。缺点是它在我们的集群中分配了大量内存。
在与 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 等公司的团队监控其云数据堆栈。Synq 建立在 ClickHouse 之上,它提供了与 ClickHouse 集群的深度集成,能够检测延迟的数据加载并发现隐藏的数据异常,并辅以自动创建的数据血缘以及用于管理数据质量的工具。
Synq 检测到的示例数据异常,其中表格中的数据量开始异常增长,原因是上游系统中的故障。
通过解析 ClickHouse 中表格、视图和物化视图的 SQL 定义提取的示例数据血缘,概述了 ClickHouse 集群内数据流的结构。
更多详细信息
- 本次演讲于 2023 年 5 月 25 日在伦敦的 ClickHouse 聚会 上发表。
- 演示文稿材料可在 GitHub 上获得。
- 了解更多信息:https://www.synq.io/