字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第1张图片

01

起源

ByteHouse 的故事从字节跳动对于先进数据处理和分析的需求开始,这一需求随着公司业务规模的迅速扩张而日益增长,起源是对开源数据库管理系统 ClickHouse 的改造和增强。面对数据处理的高延迟、大规模数据操作的复杂性以及数据存储和处理成本的上升,字节跳动的工程团队凭借多年积累的技术能力,对 ClickHouse 进行了深度定制,以满足公司不断发展的数据需求。例如,团队通过优化算法和架构,显著降低了数据查询的响应时间,并有效管理了海量数据的存储和处理。在此基础上,ByteHouse 延续并优化了列式存储和向量化查询机制,可以实现毫秒级的分析查询响应时间。并且,ByteHouse 支持标准 SQL 查询接口,并内置了贴合业务场景的高级分析函数,大幅简化了分析模型的构建和维护工作。

ByteHouse 项目的一个转折点是团队从 Snowflake 的存算一体架构中获得灵感,进而开发了基于 ClickHouse 的存算分离架构云原生数仓。这一架构使得 ByteHouse 在资源利用效率方面取得显著提升,并大幅降低了基础设施成本。具体来说,这种云原生架构通过自动将查询调度到不同的虚拟仓库,并利用 Kubernetes 管理容器化集群,实现了运维成本的显著降低。

2023 年,ByteHouse 与亚马逊云科技开展合作,共同构建了新一代的云数据仓库解决方案。通过与亚马逊云科技的无缝对接,ByteHouse 可以实现海量数据的弹性存储(基于 Amazon S3),并支持按需自动扩展计算资源(基于 Amazon EKS)。这种云原生的数据仓库架构,可帮助企业快速建立一个统一的、高性能的数据分析平台。

为实现这一目标,ByteHouse 团队与亚马逊云科技团队进行了多次深入交流和讨论,并制定了一系列详细的架构设计与性能优化方案。本文的重点会放在存算分离及其对应的性能优化过程,分享 ByteHouse 在这个过程中云上部署的一些优化经验,更多内容会在本系列后续文章中进行介绍。

02

规划

原生的 ClickHouse 是采用存算一体的 Shared-Nothing 架构,数据通常分布存储在计算节点上。这种架构确保了高效的并行计算,但也存在存储扩展性和可靠性上的局限。在转向云上 SaaS 模式后,ByteHouse 借助云计算的优势采用了 Amazon S3 这样成熟的对象存储服务,这使得 ByteHouse 实现了存算分离架构,计算资源 Shared-Nothing 和存储资源 Shared-Disk 可以根据需求独立扩展,并带来了诸多优势:

  • 计算资源和存储资源可以根据实际需求独立扩展和收缩,这确保了资源利用效率,不会出现计算资源过剩而存储资源紧张的情况,以及相反的情况。

  • 更方便实现读写分离,读操作可以直接从对象存储中获取数据,不受写操作的影响;写操作也可以高效地写入对象存储,不会影响读操作。

  • 数据存储持久性和可靠性大大提升,S3 经典的 11 个 9。即使计算节点因为故障导致服务不可用,用户也可以从 S3 中恢复数据。

ByteHouse 技术架构如下所示:

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第2张图片

同时,在设计时 ByteHouse 还要保证云上 SaaS 服务之间的多租户隔离,这里包括应用管理、资源管理和用户管理等。

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第3张图片

03

优化

在最早期的 S3 对接过程中,我们发现不做任何调优直接使用 S3 时,吞吐、延时和预期存在一定差距。S3 的对象存储本质上是为大规模非结构化数据设计的,而 ByteHouse 等分析数据库需要频繁地进行小粒度、高并发的对象访问,需要进一步的优化和调整。因此,一开始直接使用的话在性能方面还是有一定的不足,主要体现在:

  • 对象存储对比 HDFS 等分布式文件系统来说,我们观察到 P70 Latency 要大 5-10 倍,且有偶发的抖动以及多租户影响

  • 以 ClickHouse MergeTree 为主的数据访问模型,在 DFS 上占有 40% 左右的小 IO,DFS 上的 IO 预读、小 IO 合并、并发模型和条带化处理等,都无法在对象存储上直接套用

从 ByteHouse IO Layer 来看,理想状态下,延时和容量的层次图如下所示:

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第4张图片

IO 栈的优化基础,其实就是访问 S3 的时候,如何压榨资源,得到尽可能好的冷读性能。为此,ByteHouse 团队与亚马逊云科技团队进行了多次深入交流和讨论,并制定了一系列的性能优化方案,主要从计算层、存储层和网络层三个方面进行调整。

P.S. 有关在高性能数据分析领域和 S3 的有效结合,我们也学习并参考了《Exploiting Cloud Object Storage for High-Performance Analytics》论文,推荐阅读~

  • Exploiting Cloud Object Storage for High-Performance Analytics

    https://www.vldb.org/pvldb/vol16/p2769-durner.pdf

3.1 计算

计算层方面,经过详细评估,我们选择了面向不同场景的 EC2 实例类型以匹配不同的工作负载需求。在 OS 上我们也进行了多组参数调优,通过针对性的编译优化和代码优化进一步提升了计算效率,找到适合 ByteHouse 请求的线程数、队列深度、批量大小等配置。同时,我们采用了容器化的方式对计算资源进行管理,Amazon EKS 帮助 ByteHouse 简化了集群的创建、配置和管理的全过程。此外,我们计划对 Graviton 系列的 Arm 实例进行测试,以期待能为 ByteHouse 带来更高的性价比。

S3 客户端方面,ByteHouse 在后端访问时采用的是 C 语言,一开始我们采用的是 C SDK中的默认客户端(可以参考示例一),但是测试过程中性能和预期存在一定差距。接着,ByteHouse 团队测试了亚马逊云科技团队推荐的 Amazon Common Runtime 优化库,简称 CRT(可以参考示例二)。CRT 是 SDK 的基础库,也是一系列独立的模块化的家族集合,用 C 语言编写,每个包提供极致性能和并最小化资源占用。这些功能在所有 SDK 中都是可以通用和共享的(可以参考博客《Accelerate Amazon S3 throughput with the Amazon Common Runtime》),提供了更好的代码重用性、性能优化和准确性。

  • 示例一

    https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/cpp/example_code/s3/list_buckets.cpp

  • 示例二

    https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/cpp/example_code/s3-crt/s3-crt-demo.cpp

  • Accelerate Amazon S3 throughput with the Amazon Common Runtime

    https://aws.amazon.com/blogs/storage/improving-amazon-s3-throughput-for-the-aws-cli-and-boto3-with-the-aws-common-runtime/

CRT 库形成了一个略微复杂的关系和依赖网络,如下所示:

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第5张图片

CRT 整体采用了模块化的结构,因此 ByteHouse 针对特定部分的需求替换为对应的库即可。其中,amazon-crt-cpp 中封装了使用 CRT 库所需的子模块。为了加速 S3 的网络请求,减少 CPU 同步等待网络 I/O 的时间,ByteHouse 尝试使用 CRTHttpClient 替换 Amazon SDK 中默认的 HttpClient。CRTHttpClient 不仅在内部封装了 Http 连接池,可以有效地复用 Http 连接,从而减少了每次 TCP 连接的耗时。其次,CRTHttpClient 还维护了 S3 Endpoint Pool,这允许它在多个 S3 Endpoint 中实现负载均衡,这极大地改善了单个 S3 Endpoint 能提供的吞吐量。最后,CRTHttpClient 还提供了 HostCache,以避免重复的 DNS 解析。

我们在 ByteHouse 上配置 S3 作为远程存储,同时分别使用普通的 HttpClient 和 CRTHttpClient 对 SSB 100G 数据集进行查询测试。我们发现采用 CRT HttpClient 的情况下,网络吞吐明显增加,CPU 同步等待网络 I/O 的时间大幅减少,有效提高了 CPU 利用率。从查询结果上看,查询 QPS 提升 30% 以上。

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第6张图片

P.S. 更多关于 CRT 的介绍,读者可以参考这篇博客《老司机们坐稳了 – 将 Amazon EC2 到 Amazon S3 的数据传输推向 100Gbps 线速》。

  • 老司机们坐稳了 – 将 Amazon EC2 到 Amazon S3 的数据传输推向 100Gbps 线速

    https://aws.amazon.com/cn/blogs/china/pushing-the-data-transfer-from-amazon-ec2-to-amazon-s3-to-100gbps-line-speed/

此外,在 ByteHouse 的架构中,我们实施了缓存感知调度策略,专注于最大化缓存利用率并尽量减少冷读现象。这种策略通过将计算任务调度到拥有必要数据缓存的节点上,以便利用缓存来提升读写性能。此外,考虑到系统的动态伸缩性,当计算节点的拓扑结构变化时,这种策略也尽量减少由缓存失效导致的对查询性能的影响。ByteHouse 还引入了数据预热(Prewarm)和预取(Prefetch)机制,这些机制根据数据访问模式和查询分布情况,提前将数据加载到缓存中,以避免因缓存未命中而导致的冷读,从而进一步提升性能。

ByteHouse 还具备 Preload 功能,这包括预加载索引。默认情况下,引擎在启动时,即在首次查询运行之前,就会自动加载索引到缓存。这使得首次查询比最小预热时更快,但引擎的启动时间会更长。还有一种是自动预加载(auto-preload),这意味着当表发生插入或合并操作后,系统会自动将更新后的数据拉取到本地。这一功能可以通过配置项开启,使得数据处理更加高效。

3.2 存储

存储层方面,S3 在小文件对象访问时存在大量的元数据开销,这会严重影响 ByteHouse 性能。为此,我们优化了 S3 上的文件结构设计,避免过多小文件对象的产生,也不会把单个文件做的更大。经过多轮测试,ByteHouse 发现 128MB 到 512MB 的文件大小是适合自身业务的区间,这样不仅可以大幅提高读取效率,同时也减少了元数据管理的负载。

ByteHouse 采用多线程大规模并行访问 S3,针对不同文件大小和访问模式进行动态参数调优,以达到更高的并发度。另外,还通过 Range 请求方式进行分片读取,充分利用 S3 的高带宽,大幅提升了读取吞吐量。根据 Amazon S3 性能文档,典型的 Range 请求大小是 8 MB 或 16 MB,这也符合《Exploiting Cloud Object Storage for High-Performance Analytics》论文中提到的 “8 -16 Mib 大小是成本–吞吐量最优的”推论,如下图所示:

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第7张图片

除了文件大小优化外,团队研究并计划测试 Amazon S3 Express One Zone,以便显著降低存储访问延迟。re:Invent 2023 新发布的 S3 Express One Zone 是一种高性能的单可用区存储服务,专为提供稳定的单位毫秒级数据访问而设计,适用于访问频率较高的数据和延迟敏感型应用。S3 Express One Zone 可将数据访问速度提升 10 倍,与 S3 Standard 相比请求成本降低 50%,并可扩展到每分钟处理数百万请求,ByteHouse 团队计划近期对其进行性价比评测。

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第8张图片

3.3 网络

网络层方面,我们首先配置了 VPC PrivateLink 以安全访问 S3 并降低延时,提高数据访问的稳定性。在 DNS 方面,S3 在今年 8 月新推出了 DNS 多值应答(MultiValue Answer,MVA),来响应 DNS 查询。有了 MVA 之后,DNS 查询每次最多可以获得 8个 IP 地址。ByteHouse 使用这些 IP 地址自动与 S3 建立多个并发连接,从而提高了服务整体的吞吐。不仅如此,这个功能会自动尝试备用 IP 地址,而不必等待另一次 DNS 查询,为 ByteHouse 提高了重试的效率。

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第9张图片

同时,我们根据监控数据来评估不同 S3 负载均衡 IP 的延时,并在系统内优化 TCP 参数等。这些优化手段共同缩短了网络延迟,提升了 S3 访问速度。

04

效果

通过存算分离架构的改造升级以及一系列计算、存储、网络层面的系统性优化,ByteHouse 团队在亚马逊云科技平台上做了大量的基础工作和探索实验。最终,ByteHouse 在亚马逊云平台上实现了大幅的性能提升。根据内部计算存储分离前后对比的测试报告,相比原先的存储吞吐提高了 3-5 倍,延迟降低了 2 倍以上。

和开源 ClickHouse 相比,ByteHouse 在性能上也具有优秀的表现。这里以一个海外电商客户为例,他们的业务场景为数据运营系统,对比测试的条件如下:

  • 客户真实线上业务 SQL 语句 20 条(覆盖客户 80% 场景),并非 TPC-DS 等 Benchmark

  • 查询内容包括计算用户访问量、点击量、产品访问量及其转化率等

  • 高复杂度查询牵涉 Subquery、复杂 JOIN、条件逻辑、排序和限制等

  • 查询并发数为 24,计算 12 轮运行结果的平均值

  • ByteHouse 采用的 VW 大小为 96 核/384G 内存,ClickHouse 使用的规格为104 核/384G,引擎为 MergeTree

  • ClickHouse 开源版本采用的是 22.8

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第10张图片

SQL 查询结果如上所示,ByteHouse 平均执行时长比 ClickHouse 要快约 48%,最快的查询要快上 80%,效果显著。

05

小结

本文分享了 ByteHouse 在亚马逊云科技平台上云原生过程中架构升级和性能优化的一些思路。通过多个层次的优化措施,完成了整体性能上的巨大提升。随着 ByteHouse 云原生之路的不断深入,我们仍会和亚马逊云科技一起继续进行迭代升级,以适应未来的需求变化。本系列后续还会提供更多优化的分享,敬请关注。

06

打开

目前,ByteHouse 已在亚马逊云科技海外区域 Marketplace 完成上架,只需要在 Marketplace 搜索 ByteHouse 或者通过这个链接(https://aws.amazon.com/marketplace/pp/prodview-rccuf7u2vpxve)就可以进入 ByteHouse 控制台页面。有关 ByteHouse 与亚马逊云科技的数据服务对接,可以参考之前的数据集成博客系列。快来使用吧~

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第11张图片

参考资料

  • https://byconity.github.io/blog/2023-05-24-byconity-announcement-opensources-its-cloudnative-data-warehouse

  • https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html

  • https://github.com/ByConity/ByConity/commit/ca97fa91016b472bfae6692b1b0ae9c944fb96d0

本篇作者

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第12张图片

Aelfric Lin

字节跳动 ByteHouse 高级产品经理。在数据产品和 AI 产品领域拥有深厚的经验,目前专注于拓展国际市场,并在湖仓一体化、数据生态系统、大型模型等专业领域进行深入研究和实际操作。

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第13张图片

魏祥威

字节跳动 ByteHouse 高级研发工程师,专注于数据库查询引擎的功能开发和性能优化。拥有多年丰富实战经验,目前主要负责 ByteHouse 存储侧查询性能的优化。

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第14张图片

史天

亚马逊云科技资深解决方案架构师。拥有丰富的云计算、数据分析和机器学习经验,目前致力于数据科学、机器学习、无服务器等领域的研究和实践。译有《机器学习即服务》《基于 Kubernetes 的 DevOps 实践》《Kubernetes 微服务实战》《Prometheus 监控实战》《云原生时代的 CoreDNS 学习指南》等。

星标不迷路,开发更极速!

关注后记得星标「亚马逊云开发者」

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第15张图片

听说,点完下面4个按钮

就不会碰到bug了!

字节跳动 ByteHouse 云原生之路 – 计算存储分离与性能优化_第16张图片

你可能感兴趣的:(云原生,性能优化)