深入探索 RisingWave meta store 的演进历程

文摘   科技   2024-10-25 16:31   北京  

自 1.8 版本开始,RisingWave 就支持将 SQL backend 作为元数据存储(meta store),用户可选择使用 PostgreSQL、MySQL 或 SQLite 来替代 etcd。而在即将发布的 2.1 版本中,RisingWave 将正式停止对 etcd 作为 meta store 的支持。使用 etcd 作为元数据存储的 RisingWave 集群升级到 2.1 时需要迁移到 SQL backend[1] 上。

那么,meta store 在 RisingWave 集群中究竟扮演着怎样的角色?使用 etcd 作为 meta store 时遇到了哪些问题?将 meta store 从 etcd 迁移至 SQL backend 又是如何解决这些困难,并带来了哪些显著优势?本文将引领读者深入探索 RisingWave meta store 的演进历程

1RisingWave 的元数据存储

下面是 RisingWave 的架构简图,可以看到其内部有 frontend、compute node、compactor、meta server 等多种节点。

RisingWave 设计之初就决定拥抱云。为了充分利用云平台提供的弹性资源,云原生架构下,大部分节点都是无状态的节点。集群的持久化状态存储在各节点共享的存储系统上,分成了两部分:

  • 在图下方的集群的持久化数据存储。这包括表和 MV 的数据,以及流计算的状态存储。这部分数据被组织成 LSM 树的格式,存储在对象存储服务(Object Storage Service,OSS)上,例如 AWS 的 S3 存储。
  • 图右侧的集群的元数据存储(meta store)也是本篇文章的主角。这里存储了所有 Catalog 和用户信息、前面提到的 LSM 树的元信息和结构,以及所有流任务的拓扑结构以及其在计算节点上的分布。

meta server 节点直接读写元数据存储,是 RisingWave 集群的“大脑”,它和集群中的其他节点通信,实现集群的各种管理和变更功能,包括:

  • 元数据管理不同对象的创建、修改和删除。对于一些有对应流任务的对象,meta server 需要和计算节点交互,创建、修改和删除上面的流计算任务。
  • 调度和管理计算节点上的计算任务,包括迁移,scale in/out 等操作。
  • 发起和管理集群的 checkpoint
  • 管理 LSM tree,调度和发布 compaction 任务。

2使用 etcd 作为元数据存储

在最早,我们使用了 etcd 来作为元数据存储,出于方便维护和兼容性考虑,元数据被编码为 protobuf。作为饱经考验的元数据系统,etcd 很好地满足 RisingWave 对元数据存储高可用、持久化和事务处理的需求。但随着 RisingWave 的不断演进,用户集群的规模不断增长,我们开始遇到很多问题。

开发复杂度高

etcd 作为一种键值存储,采用 KV 模型,虽然能够很好满足 Catalog、权限管理等结构简单、层次明确的元数据需求,但在处理复杂场景时显得力不从心。它无法原生支持多个字段到同一条记录的索引,如同时通过表名和表的 ID 高效查询表的元信息。此外,etcd 本身并不具备数据处理能力,一个需求可能需要通过多次查询才能满足。

例如,对于流计算图的维护和更改,etcd 的 KV 模型显得捉襟见肘。在计算图中,一个常见的需求是根据流计算任务的依赖关系,判断这些任务是否构成环路。如果直接在 etcd 上实现这一功能,meta server 需要反复迭代查询 etcd,这样的时延是无法接受的。

为了应对这一挑战,我们在 meta server 的内存中全量缓存了一份元数据。这样,在需要读取元数据时,可以直接访问内存,同时,在内存中也可以对元数据进行各种索引。然而,这份内存元数据的引入,除了对 meta server 的内存资源有比较高的要求之外,还增加了复杂度和开发者心智负担。开发者需要在更新 meta store 时手动维护缓存元数据,确保其与 etcd 保持一致。在 etcd 的事务提交成功或失败后,内存中的元数据也需要相应地进行提交或回滚。许多与 meta server 相关的 bug,都是由于内存元数据与 etcd 不一致,或者内存中元数据发生竞争或死锁导致的。

云上运维困难

etcd 通常面向的是裸机部署场景,而云厂商并未提供 etcd 的云上托管服务。因此,RisingWave Cloud 必须自行解决在云上部署 etcd 的问题。在短暂尝试开发 etcd operator 后,我们最终决定使用 Helm 在云厂商的托管 Kubernetes 服务(如 Amazon EKS)上部署 etcd

在实际运维过程中,有状态的分布式存储给我们带来了不小的维护压力。许多工程师在解决 RisingWave 的线上问题时游刃有余,但面对 etcd 时却感到无从下手。常见的问题包括在大量请求后出现 OOM、etcd 未能及时进行 defrag 等。要彻底解决这些问题,往往需要深入探究并进行参数调优。另一方面,这些问题在一定程度上也与云上的磁盘性能略逊于本地磁盘有关。

种种挑战促使我们开始思考,在云上是否有更优的选择。

数据量上限

etcd 设计之初没有打算承担大规模的数据存储。这在设计上最明显的体现是其采用单 Raft Group 而没有实现 sharding。这使得其很多优化目标、实现、以及工业实践的使用都是在小数据规模下的。目前,其默认存储限制为 2 GB,推荐的最大数据量也只有 8 GB(参见文档[2] )。

起初,RisingWave 对单集群元数据的预估也不超过 GB 级别。我们原本设想,由于业务需求和维护成本的限制,单个集群内的流任务数量应该是有限的。然而,在实际应用中,我们发现有些用户通过脚本能够轻松创建和管理上千个物化视图。这个数字经过 SQL 的复杂度和并行度两重放大,产生了未预料的元数据大小,百万级的 Actor(RisingWave 中调度的最小单元)并没有开始预想的那么遥远。在 RisingWave Cloud 上,在 scale out 等元数据高频更新场景下由于 etcd 内 LSM 本身的放大,一些RisingWave 集群 etcd 的 4GB 磁盘很快耗尽。许多用户集群的元数据一直在持续增长当中,这让我们开始为未来考虑。

另一方面,对于大多数用户来说,他们的元数据规模其实非常小,每个集群都占用一个独立的 etcd 节点,造成了资源浪费。etcd 的不可扩展性也限制了元数据存储多租户部署的潜力。

其他问题

除此之外我们还遇到了一些问题,或大或小,体验不佳。例如:
  • 在磁盘耗尽恢复后,事务部分提交导致脏元数据。具体原因仍未查明。
  • 采用 protobuf encoding 导致查错困难。用户需要编写脚本来查找所需信息。如果遇到脏数据,手动订正时同样需要借助脚本,这增加了操作的复杂性。
  • etcd 被设计用于处理较小的键值对。默认限制了 RPC 的大小在 1MB(参见开发指南[3])。而随着执行计划等元数据包含的字段越来越多,单条元数据的大小也在持续增大。UDF 等功能也带来了较大的单条字段。

3使用 SQL backend 作为元数据存储

面对这些挑战,我们开始考虑使用 SQL backend ,直接采用 OLTP 系统来作为 RisingWave 集群的元数据存储。这不仅能满足高可用、持久化和事务处理的基本需求,还能解决前文提到的问题。具体来说,使用 SQL backend 作为元数据存储有以下优点:

  • 在开发复杂度方面,使用 SQL backend,开发者可以为元数据表创建索引,并且可以用 SQL 语句来表达原本在 meta server 上的查询逻辑。这样一来,meta server 上的缓存就不再需要了。例如,前文提到的找环逻辑,在 SQL 中只需一个 recursive CTE 语句就能轻松表达,所有的计算都将在作为 Meta Store 的数据库上进行。
  • 在云上部署方面,RisingWave Cloud 可以利用云厂商托管的数据库服务。RDS 等各类数据库服务始终是各家云厂商的核心产品,因此可以获得良好的支持。
  • 在数据量限制方面现代的关系型数据库普遍可以支持 TB 级别的数据,用来存储元数据,大大扩展了 RisingWave 的应用范围。对于云厂商的 RDS 服务也在这个级别,例如 AWS RDS PG[4]就支持最高 128 个 vCPU 和 4096 GiB RAM,64TiB 存储
  • 此外,使用 SQL backend 为多租户共享元数据存储提供可能。元数据的数据量和并发度通常都比较有限,对 OLTP 数据库来说是轻负载,多个 RW 集群共享同一个数据库做共享元数据存储可以减少资源浪费。不过,共享机制在元数据存储故障时影响范围扩大,我们正通过更多测试与实验来权衡其利弊。

4结论

从 1.3 版本着手开发,到 1.8 版本完整实现所有功能并公开发布,再到 2.1 版本正式停止对 etcd 的支持,整个过程历时颇久。在此期间,Meta Server 上的各项功能始终在持续开发中,同时我们还要确保功能和性能不出现重大回退。从 etcd 切换到 sql backend 的难度和风险可想而知,无异于在飞行的飞机上更换引擎。经过团队的不懈努力,我们在这个版本终于完全切换到了 sql backend,成功实现了平稳过渡。鉴于 SQL backend 依然是一个较新的功能,用户在使用中依然可能会遇到问题。我们热烈欢迎大家给我们提供反馈,共同完善 RisingWave 这一广受喜爱的流式数据库系统。
参考资料
[1]

迁移到 SQL backend 上: https://docs.risingwave.com/docs/current/migrate-to-sql-backend/

[2]

文档: https://etcd.io/docs/v3.5/dev-guide/limit/

[3]

开发指南: https://etcd.io/docs/v3.5/dev-guide/limit/

[4]

AWS RDS PG: https://aws.amazon.com/cn/rds/features/

关于 RisingWave 

RisingWave 是一款基于 Apache 2.0 协议开源的分布式流数据库,致力于为用户提供极致简单、高效的流数据处理与管理能力。RisingWave 采用存算分离架构,实现了高效的复杂查询、瞬时动态扩缩容以及快速故障恢复,并助力用户极大地简化流计算架构,轻松搭建稳定且高效的流计算应用。
RisingWave 始终聆听来自社区的声音,并积极回应用户的反馈。目前,RisingWave 已汇聚了 150+ 名开源贡献者和 3000+ 名社区成员。全球范围内,已有上百个 RisingWave 集群在生产环境中部署。

往期推荐

技术内幕

如何上手 RisingWave 👉 新手入门教程

RisingWave 中文用户文档上线,阅读更高效!

深入探索 RisingWave 中的高可用性与容错机制

深入理解 RisingWave 流处理引擎(三):触发机制

深入理解 RisingWave 流处理引擎(二):计算模型

深入理解 RisingWave 流处理引擎(一):总览

用户案例
视源股份(CVTE)IT 流计算应用历程
尘锋 SCRM 如何使用 RisingWave 实时打宽
RisingWave 在超百亿管理规模对冲基金公司中的应用
金融科技公司 Kaito 使用 RisingWave 实现实时智能化
龙腾出行如何通过 RisingWave 实现实时数据分析
RisingWave 助力乾象投资打造实时监控平台

RisingWave中文开源社区
RisingWave 是一款开源分布式 SQL 流数据库,致力于大幅降低流计算使用门槛与复杂度。RisingWave 已为全球超百家企业构建新一代流处理与分析平台。
 最新文章