暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

S3 也能跑出内存级性能?深入解析 S3 作为 RW 主存储的架构设计

吴英骏
来源|RisingWave 官网
这几年,“S3 作为主存储”的概念被炒得火热。你肯定看过类似的架构图:计算和存储分离,数据全部存进云端,弹性无限,听起来一切都很美好。但真要将它落地到一个对 SLA(Service Level Agreement,即服务可用性和稳定性)要求高的企业系统中时,很快就会发现,这远没有想的那么简单。

在 RisingWave,我们选择了一条更难的路。从一开始,我们就决定将 S3 用作唯一的存储层,而不仅仅是备份用途。无论是内部状态、物化视图、算子输出,还是恢复日志,全部都存放在 S3 上。

这一选择迫使我们针对需要解决出现的各种限制问题:读写延迟高、API 请求贵、无法保证强一致性、完全不支持传统磁盘语义……

但我们成功了。我们构建出了一套架构,让以 S3 为基础的系统也能提供接近内存系统的性能与一致性。

本文将逐步揭示我们是如何一步步实现这一目标的——每一次尝试、每一课教训,全部呈现,毫无修饰、直击核心、拒绝废话。


S3 是对象存储,不是文件系统

很多系统一开始是基于本地磁盘或 EBS(弹性块存储)卷设计的。然后某天有人说:“我们把它迁移到 S3 吧。”听起来很简单?但动手实践会发现这等于是一次重写。

S3 并不是磁盘的直接替代品:它不支持随机定位(seek)、追加写(append)或重命名(rename)。它是不可变的,最终一致的,而且每一次读写都存在较高延迟。如果你的系统依赖随机访问、同步写入或文件级原子性——那 S3 会彻底打破你的假设。

RisingWave 从设计之初就决定以 S3 作为主存储,而不是事后迁移。因此,从状态模型到 compact 策略再到恢复机制,全都围绕对象存储进行设计。

我们将所有数据写成不可变的 blob:比如物化视图、中间状态和算子的输出。这些数据会按照表 ID 和 epoch 进行组织和版本管理,写入之后不会被修改。元数据存在 Postgres 里,负责记录每个对象的归属以及怎么恢复。

这让计算节点真正“无状态”:当节点宕机或替换时,只需向 Postgres 询问恢复位置,再从 S3 拉取所需数据。无需本地 RocksDB,无需协调协议。RisingWave 能具备良好的容错性和弹性,正是因为从一开始就为 S3 而设计,而不是后来才强行兼容。


延迟是首要难题

在流处理系统中,内部状态至关重要。每个算子,例如 join、窗口或聚合操作,都依赖于在海量事件之间维护状态。但如果这些状态直接存放在 S3 上,系统将无法正常运作。

S3 非常慢。最佳情况下,TTFB(首字节时间)大概为 30ms,但现实中更常见的是 100–300ms,尤其在高负载时。如果你每秒处理 1000 个事件,且每个事件都需要读写状态——几百毫秒的延迟会迅速累积,最终系统拖垮。

当然,我们用内存缓存。但内存有限——大多数云机器的内存只有 32 到 64 GB,除非你愿意为高配花大钱。而这远远不够支撑涉及大窗口或海量 join 的复杂查询。

因此,我们引入了中间层:本地磁盘,更具体地说,是 NVMe SSD 或 EBS,作为内存和 S3 之间的“温存层”。

有人可能会质疑:“EBS 比本地 SSD 慢太多。”但其实不完全对,事情没那么简单。

EBS 实际上有很多优势:

  1. 并非所有实例类型都带本地盘:在 AWS 上,只有部分实例系列支持 NVMe,本地盘机型往往配置过剩,不适合轻量计算场景。
  2. 磁盘大小可调节:本地盘大小受限于实例配置,EBS 可以单独扩容或缩容。对只跑简单聚合任务的租户而言,不必为闲置磁盘付费。
  3. 部署可移植性强:RisingWave 可运行在 AWS、Azure、GCP 甚至本地环境。所有平台都有类 EBS 的块存储,而本地盘配置则千差万别,不易标准化。
  4. 现代 EBS 已足够快:如使用 io2 这类高性能配置,EBS 能提供稳定、高吞吐的 IOPS,足够支撑中间状态缓存。

我们还构建了 Foyer[1],一个运行在磁盘层的智能缓存系统,支持数据驱逐与指标采集,并深度集成在 RisingWave 的查询引擎中。内存、SSD、S3 各司其职。S3 成为真正的长期、不可变、低成本的持久层,只有在万不得已的查询路径中才会访问。

压缩必须远程进行

当内部状态分布在内存、磁盘和 S3 上时,必须有机制对这些数据做结构化整理,特别是磁盘和 S3 上的部分,才能保证读取效率,同时避免存储空间迅速膨胀。这正是 compaction 要解决的问题。

RisingWave 使用类似 LSM-tree 的架构来管理这套分层存储。不过我们没有像 RocksDB 那样在本地做 compaction,而是把它完全拆分出去。RocksDB 这种做法容易造成资源冲突:如果查询负载很重,同时又触发了 compaction,CPU 和 I/O 会互相争抢,系统就容易卡顿。而对流处理系统来说,这种卡顿是致命的。

我们的解决方案是 remote compaction:专门的压缩节点从 S3 拉取状态数据,完成合并后再写回 S3,全程不干扰计算节点。这样查询延迟保持稳定,计算节点专注执行任务。

但为压缩单独配机器可能造成资源浪费,尤其是在负载波动时。因此在 RisingWave Cloud 中,我们更进一步,将压缩设计为无服务器(serverless):多租户和多任务共享压缩资源池,按需扩展,自动缩放,无需手动运维。

在私有部署场景下,也可以选择运行轻量的压缩节点,安静高效地完成幕后工作。

通过这样的设计——内存用于加速、EBS/SSD 作为缓冲、S3 做持久化、远程压缩重组数据——RisingWave 能够应对各种工作负载,既快又稳。


访问 S3 的方式决定费用

S3 的计费方式不只是“存多少”,更关键是“怎么用”。每一次 API 调用都收费,不管是 GET、PUT、LIST 还是 HEAD。如果你的系统每天对 S3 进行上百万次小读操作,那 AWS 账单可能比存储本身还贵。

实际案例显示:每天 100 万次 GET 请求,每次 $0.0004,每月就要 $400,再乘以多个租户和 30 天,很容易就达到数千美元。

所以我们系统性地避免这个陷阱:

  • 块级读取(Block-level reads):将逻辑行打包成 4MB 块,这是 S3 GET 成本与预取效率的最佳平衡点,每次只需一个请求。
  • 稀疏索引(Sparse index):每个表、每个视图、每个物化结果都配备小巧索引,映射逻辑 key 范围到 S3 对象和偏移。这些索引保存在内存或 SSD 中,避免盲目读 S3。
  • 预取机制(Prefetching):查询规划阶段,RisingWave 分析扫描模式,提前加载所需块。例如查询需要 Blocks 1–10,系统会在返回 1 的同时在后台抓取 2 到 10。

这一机制能将 S3 请求次数减少 80–90%,大幅降低查询成本,是在实时系统中可持续使用 S3 的关键。


实时性与一致性,缺一不可

在流处理系统中,结果“新不新”至关重要。没人愿意跑个查询却看到 30 分钟前的数据,用户要的是真正的“实时”。

为此,我们实现了以下功能:

  1. 写完马上能读到最新数据
  2. 写入到查询节点,数据迅速同步
  3. 缓存失效快,数据保持干净

每次写入都会触发事件,失效相关缓存块(内存和磁盘),物化视图增量更新,避免等待全量重算。冷数据快速驱逐,旧快照不会残留。

这套架构保证:只要事件进入系统,下游查询几秒内就能反映更新。不是最终一致,而是立刻一致。这正是 RisingWave 呈现“实时感”的关键。


多租户与资源隔离

S3 从根本上改变了多租户架构。传统做法是给每个租户单独建集群,配备专属磁盘和缓存,但存储都放在 S3 后,情况不同了。

RisingWave 把所有持久数据都放到 S3 上,租户不再抢本地磁盘。每个查询和物化视图都从同一个对象存储拉数据,但用各自的逻辑命名空间管理。这样,就不用划分磁盘,也不用担心一个租户影响别人的缓存了。

因此我们得以在计算层实现真正隔离:

  • 每个查询的 CPU 限额,由执行引擎强制控制
  • 租户级内存配额,并结合 SSD 和 S3 缓存层实现驱逐机制
  • 独立的 I/O 预算,防止某个高负载任务拖慢整个系统

同时,所有租户共享元数据目录,使得不同团队可以协同使用相同数据流或物化视图,无需复制或担心性能冲突。

借助 S3 作为统一的数据源,加上 RisingWave 无状态的执行层,多租户不仅可行,而且更加简洁、高效、稳定。


缓存预热与节点间传输

S3 是优秀的持久层,但绝不是适合高频访问的热数据来源。因此我们让 RisingWave 在数据更新时主动预热缓存。

每次写入(比如新的 CDC 批次,或视图更新)都会立刻通知读路径,触发预取逻辑,提前加载相关磁盘和内存缓存。这样下一个查询命中时,不必等待 S3 GET。

未来我们还有进一步的计划,打算支持点对点缓存同步,即一个节点能直接把热点数据块传给另一个节点。这样,读取节点不必每次都访问 S3,而是能从邻近的、刚写入该数据块的节点那里获取数据。可以理解为一种内部 CDN,专门为快速传播事件而设计。

在计算资源弹性且 S3 访问代价高的情况下,这种机制尤为关键。减少对对象存储热点读取的依赖,系统规模扩大时的性能表现会更出色。


结语

构建一个以 S3 为主存储的流式数据库,不仅难度大,而且挑战极高。你需要对系统的各个层面进行彻底重构,包括缓存策略、状态管理、数据合并、查询刷新和协调机制。过去关于磁盘、内存和文件操作的常规思路,在这里完全失效。

但如果你真的做成了,收获将是巨大的:

  • 任何节点都能瞬间重启,且不会丢失数据
  • 可以自然地跨区域和多云扩展
  • 不用担心磁盘空间不足或 SSD 故障
  • 以对象存储的成本获得完整的弹性和持久性
  • 最重要的是,得益于智能缓存和远程压缩,依然能达到内存级别的性能

我们构建的是这样一个系统:S3 负责冷数据持久化,EBS 或本地盘管理温状态,内存处理热路径,背后由压缩引擎动态重组。这一切看起来像内存数据库,运行成本却遵循云经济模型。

如果你想亲自体验在生产环境中的表现,可点击阅读原文立即体验 RisingWave,感受我们用四年时间打造的稳定与高效。这是专为挑战极限设计的架构,你只需专注于业务,剩下的交给 RisingWave。

参考资料
[1]

Foyerhttps://foyer.rs/

关于 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中文开源社区,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论