从Postgres到ScyllaDB NoSQL,速度提升349倍

译文
数据库
看看Coralogix如何将查询处理时间从30秒缩短到86毫秒,以及如何借助WebAssembly和Rust进行下一步优化。

译者 | 布加迪

审校 | 重楼

速度对于Coralogix而言很重要,这是一个开发团队信任的可观测性平台,可以及时发现问题Coralogix使用实时流分析管道,提供监控、可视化和警报功能,无需索引。

Coralogix主要的差异化优势之一是分布式查询引擎,可以快速查询远程存储客户归档中的映射数据。该引擎使用特殊的Parquet格式查询存储在对象存储Google Cloud StorageS3中的半结构化数据。它最初底层对象存储上的无状态查询引擎,但是在查询执行期间读取Parquet元数据带来不可接受的延迟影响。为了克服这个问题,团队开发了一个元数据存储简称为Metastore”),以便更快地检索和处理执行大型查询所需的Parquet元数据。

最初的Metastore实现建立在PostgreSQL之上,速度不够快,无法满足公司的需求。因此,团队尝试了一种新的实现这次使用ScyllaDB,尝试取得了成功。团队取得了显著的性能提升——查询处理时间从30缩短86毫秒。不妨深入了解一下他们是如何做到这一点的,并了解一下他们计划如何使用WebAssembly用户定义函数(UDF)和Rust进一步优化它。

Metastore动机和需求

在讨论Metastore实现细节之前,不妨介绍一下当初构建Metastore理由

Coralogix的首席软件工程师Dan Harris解释道:“我们最初将这个平台设计为底层对象存储之上的无状态查询引擎,但我们很快意识到,查询执行期间读取Parquet元数据的成本占查询时间的很大一部分。他们意识到可以通过将Parquet元数据放在一个可以快速查询的快速存储系统中而不是直接从底层对象存储读取和处理Parquet元数据加快速度。

他们设想解决方案具有以下功能:

  • 以分解格式存储Parquet元数据,从而获得高扩展性和吞吐量
  • 使用布隆过滤器有效地识别每个查询要扫描的文件
  • 使用事务提交日志以事务性方式添加、更新和替换底层对象存储中的现有数据

关键需求包括低延迟、读/写容量方面的可扩展以及底层存储的可扩展性。为了理解所需的极端可扩展性,请考虑这种情况:单单一个客户每小时生成2000个Parquet文件每天50000个,总计每天15TB,因此单单一天仅Parquet元数据就有20GB。

最初的PostgreSQL实现

Harris承认:“我们在Postgres上开始了最初的实现,当时我们明白从长远来看,非分布式引擎是不够的。最初的实现存储诸如块(block)之类的关键信息,表示一行组和一个Parquet文件。这包括元数据,比如文件的URL、行组索引和关于文件的少量细节。比如说:



为了优化读取操作,他们使用了布隆过滤器进行高效的数据修剪。Harris解释道:“最终,我们希望支持全文搜索之类的操作大致来说,当我们将这些文件摄取到系统中时,可以为我们在文件中找到的所有不同的令牌构建一个布隆过滤器。然后,根据特定的查询,我们可以使用这些布隆过滤器来修剪我们需要扫描的数据。

们将布隆过滤器存储在块分割的环境中,将它们分成32字节大小的块,以便高效检索。它们独立存储,因此系统不必在查询时读取整个布隆过滤器。

此外,它们为每个Parquet文件存储列元数据。比如说:

Harris解释:“我们写的文件内容相当宽,有时多达2万列。因此,如果只读取我们需要的元数据,可以真正减少任何特定查询所需的IO数量。

ScyllaDB实现

接下来,不妨看看由Harris的同事、Coralogix的高级软件工程师Sebastian Vercruysse概述的ScyllaDB实现。

数据建模

了新的实现,必须重新考虑块建模。这里有一个块URL的例子:s3://cgx-production-c4c-archive-data/cx/parquet/v1/team_id=555585/…

…dt = 2022-12-02 / hr = 10/0246f9e9-f0da-4723-9b64 a12346095d25.parquet

粗体部分是客户的顶层存储存储桶内,各项按小时划分。在这种情况下,应该使用什么作为主键

  • 表url)?但有些客户比其他客户拥有更多的Parquet文件,他们希望保持平衡。
  • ((块url,行组))?这标识了特定的独特身份,但是很难列出某一天的所有块,因为时间戳不在中。
  • ((表url,小时))?这很管用,因为如果你有24小时的查询时间,很容易查询。
  • ((表url,小时),块url行组)?这是他们选择的。通过将块URL和行组添加为聚簇键,他们可以在一小时内轻松检索某个特定块,这也简化了更新或删除块和行组的过程。

布隆过滤器分块和数据建模

下一个挑战是考虑到ScyllaDB没有提供相应的开箱即用功能,如何验证某些位是否已设置。团队决定读取布隆过滤器并在应用程序中处理它们。不过记住,他们每天为每个客户处理多达50000个块,每个块含布隆过滤器部分262KB。总共是12GB——对于一个查询来说太大了,无法拉回到应用程序中。但他们不需要每次都读取整个布隆过滤器只需要其中的一部分,这取决于查询执行期间涉及的令牌。因此,他们最终将布隆过滤器分成几行,这将读取的数据减少到易于管理的1.6 MB。

对于数据建模,一种选择是使用((block_url, row_group,块索引作为主键。这将为每个布隆过滤器生成8192个32字节的块,从而生成每个分区约262 KB的均匀分布。对于同一分区中的每个布隆过滤器,使用单个批处理查询就可以轻松插入和删除数据。但是有一个问题会影响读取效率在读取布隆过滤器之前,您需要知道块的ID。此外,该方法需要访问大量分区5万个块意味着5万个分区。正如Vercruysse特别指出:“就算使ScyllaDB这样快的技术,仍然很难5万个分实现亚秒处理。

一个选项(这也是他们最终决定的):((表url,小时,块索引,块url,行组。请注意,这是与块相同的分区键,只是在分区键上添加了一个索引,该索引表示查询引擎所需的第n个令牌。使用这种方法,扫描24小时时间窗口的5个令牌可生成120个分区——与之前的数据建模选项相比,这个改进很出色。

外,这种方法在读取布隆过滤器之前不再需要块ID,从而允许更快的读取。当然,总存在不足之处。在这里,由于阻塞布隆过滤器方法,他们不得不将单个布隆过滤器拆分为8192个独特分区。与之前允许一次摄取所有布隆过滤器块的分方法相比,这最终限制了摄取速度。然而,能够在一小时内快速读取某个块比快速写入来得更重要,因此他们认为这种取舍是值得的。

数据建模问题

毫不奇怪,从SQL迁移到NoSQL需要大量的数据建模返工,包括一些试错。比如说,Vercruysse表示:“有一天,我认识到我们弄乱了最小和最大时间戳——我想知道我该如何修复它。我想也许可以重命名这些列,然后让它重新运行。但是,如果列是聚簇键的一部分,你就无法重命名列。我想也许可以添加新列并运行UPDATE查询来更新所有行。遗憾的是,这在NoSQL中也行不通

最终,他们决定截断表并重新开始,而不是编写迁移代码。在这方面,他们给出的最好建议是第一次就把事情做好。

性能提升

尽管需要进行数据建模工作,但迁移收到了很好的成效。对于Metastore块列表

  • 每个节点当前处理4到5 TB的数据。
  • 他们目前每秒处理大约1个写操作,P99延迟始终低于1毫秒。
  • 列表在一小时内生成了大约2000Parquet文件;就布隆过滤器而言他们的处理时间不到20毫秒。对于5万个文件,处理时不到500毫秒。

他们还执行了位校验。但是对于5万个Parquet文件而言,500毫秒可以满足需求。

在列元数据处理中,P50相当不错,但尾部延迟较高。Vercruysse解释:“问题在于,如果我们有5万个Parquet文件,我们的执行器会并行获取所有这些文件。这意味着我们有很多并发查询,我们没有使用最好的磁盘。我们认为这是问题的根源。

ScyllaDB设置

值得注意的是,Coralogix从最初发现ScyllaDB到部署到拥有TB级数据生产环境仅用了两个月(这是需要数据建模工作的SQLNoSQL迁移,而不是简单得多的Cassandra或DynamoDB迁移

实现是在ScyllaDB Rust驱动程序上用Rust编写的,他们发现ScyllaDB Operator for Kubernetes、ScyllaDB Monitoring和ScyllaDB Manager都对快速迁移大有帮助。由于为他们自己的客户提供低成本的可观测性替代方案对Coralogix很重要,因此团队对他们的ScyllaDB基础设施的性价比感到满意一个三节点聚簇有以下配置:

  • 8个vCPU
  • 32 GB内存
  • Arm/Graviton
  • 带宽为500mbps、IOPS为12k的EBS卷gp3

使用ARM可以降低成本,而决定使用弹性块存储EBS)(gp3卷最终归结为可用性、灵活性和性价比。他们承认:“这是一个有争议的决定,但我们正在努力让切实可行,我们会看看我们能坚持多久。

汲取的经验

他们在这里学到的主要经验是

  • 注意分区大小使用ScyllaDB与使用Postgres的最大区别是,您必须非常仔细地考虑分区和分区大小。有效的分区和聚簇键选择对性能有很大的影响。
  • 考虑读/写模式您还必须仔细考虑读/写模式。您的工作负载是不是读取密集型?它是否涉及搭配均衡的读写操作?或者,入操作为主?Coralogix的工作负载有大量的写入操作因为他们不断地摄取数据,但需要优先考虑读取操作,因为读取延迟对业务来说最关键。
  • 避免EBS团队承认他们被警告不要使用EBS:“我们没有听从,但我们可能应该听。如果您在考虑使用ScyllaDB,那么查看具有本地SSD的实例而不是尝试使用EBS卷可能是好主意。

未来计划:结合使用WebAssembly UDF和Rust

将来,他们希望在写入足够大的块和读取不必要的数据之间找到折衷。他们将数据块分成大约8000行,认为可以进一步分成1000行,这有望加快插入速度。

们的最终目标是通过充分利用WebAssembly的用户定义函数(UDF),将更多的工作给ScyllaDB处理。使用现有的Rust代码,集成UDF不需要把数据发回应用程序,为分块调整和潜在的改进提供灵活性。

Vercruysse表示:“我们已经用Rust编写了所有内容。如果我们可以开始使用UDF,这样我们不必向应用程序发任何其他内容。这给了我们更余地来处理分块。

原文标题:From Postgres to ScyllaDB NoSQL, with a 349x Speed Boost,作者:Cynthia Dunlop


责任编辑:华轩 来源: 51CTO
相关推荐

2023-09-12 12:14:05

Python程序矢量化

2009-12-24 09:30:38

Opera性能测试

2017-05-11 11:30:43

MySQL查询速度

2009-03-29 09:47:24

苹果Iphone移动OS

2017-05-10 16:09:12

MySQL数据库查询

2024-03-19 14:43:17

自动驾驶激光

2024-01-19 13:41:00

AI模型

2020-09-20 21:46:00

量子芯片网络

2011-04-01 09:29:52

MySQLMongoDB

2021-12-27 06:57:40

Maven工具性能

2023-03-22 13:53:26

芯片英伟达

2022-04-06 11:10:00

模型训练项目

2009-11-26 11:29:46

Silverlight

2020-11-19 15:02:56

TensorFlow数据机器学习

2021-11-22 16:35:59

WiFi 6WiFi 7技术

2014-11-11 15:57:07

2024-03-18 09:02:53

AI模型

2021-04-14 15:03:16

数据性能存储

2021-09-30 11:27:58

模型人工智能神经网络
点赞
收藏

51CTO技术栈公众号