Google Vortex流式存储引擎分析

作者:archimekai,转载请注明出处

参考文献: Edara, P., Forbesj, J., & Li, B. (2024). Vortex: A Stream-oriented Storage Engine For Big Data Analytics. Companion of the 2024 International Conference on Management of Data, 175--187. https://doi.org/10.1145/3626246.3653396

文章目录

Vortex: A Stream-oriented Storage Engine For Big Data Analytics

免责声明:为了行文连贯,本文中掺杂了一些笔者的推测,请务必对照原论文阅读以免被误导。欢迎批评指正!

为什么?

在数据流(continuous stream)上的数据分析,缩短了从数据产生,到洞察见解的时间。为了更好地支持数据流上的分析,Google BigQuery构建了Vortex系统以支持实时分析。Vortex是一个把数据流放在首要位置的存储系统,其既能支持流式分析,又能支持批处理。借助于Vortex,BigQuery能够支持PB级数据的亚秒级导入和查询。

现有批量数据处理的问题

  • 新鲜度:流式数据处理对数据新鲜度的要求较高,现有的离线批量数据导入架构(新鲜度在小时级、天级)无法满足。
  • 数据丢失:生成流式数据的应用,通常运行在资源高度受限的环境中。这样的应用难以在本地缓存较多数据,常常需要对数据进行采样以减少数据量,导致数据流式。
  • 多次拷贝:批量数据处理中需要多次将中间结果写入临时存储,增加了数据处理时延,难以进行数据管理

路线选择

  • 路线一:将现有的批处理改造为支持处理流式数据(Spark)
  • 路线二:专门为流式数据处理构建系统,然后将这个系统也用在批处理上(Flink)

Vortex选择了后者。

是什么?

Vortex是一个专为(流式)追加写(append)优化的存储引擎。

  • 在架构上,Vortex是高度分布式的,在*region粒度(TODO 待确认)*进行数据复制(可用性较高)的存储引擎
  • 在可扩展性上,vortex的数据面和控制面均是分布式的,能够支持单表PB级数据
  • 在API上,Vortex为批处理和流处理提供了统一的API
  • 在事务能力上,Vortex的所有API均支持ACID性质
  • 在性能上,vortex提供亚秒级写入的SLA,这样客户端无需预留很大的buffer缓存要写入的数据
  • 在数据类型上,Vortex支持结构化和半结构化数据(见Dremel论文,本次不介绍)

下面本文将从核心概念,架构,API,写入读取流程等方面对Vortex进行分析,并总结一些vortex设计中值得我们借鉴的思路。

核心概念

如上图所示,stream是Vortex的核心概念,笔者将围绕stream展开介绍。

vortex stream

Vortex Stream(下文简称stream)是基于BigQuery Table的抽象。在同一个BigQuery Table上,可以同时存在多个stream,因此一个BigQuery Table也可以被视为多个stream的集合。

stream是用来承载写入和读取操作的实体。用户将要写入的行追加到stream的末尾(注意每个stream在当前时刻的末尾都是确定的)。当前已写入stream的行数,也被叫做stream的长度(length)。每一个写入stream的行,都会获得一个row offset。一个客户端可以创建一个或多个stream并发写入同一张表。一张表可以支持上万个客户端同时写入(从而能够达到很快的并发写入速度)。

同一个stream可以被多个reader并发读取。

在Vortex系统内部,一个stream由若干个streamlet组成,一个streamlet又由若干个fragment组成。

streamlet

streamlet由一组连续的行组成,是数据持久性(数据复制)管理的最小单位。为了保证数据的持久性(durability),每行数据(每个streamlet)至少要被写入两个borg cluster才会被认为写入成功。一个stream由一个或多个streamlet组成。stream中最多有一个streamlet是可写的,其必然是stream中的最后一个streamlet。对于可写的streamlet,其元信息(例如streamlet的当前长度)由stream server管理,spanner中保存的元信息仅作为缓存使用。对于已经写完的streamlet,spanner中会保存准确的元信息。

备注:streamlet有点类似于CU。

fragment

streamlet中的行可以进一步被分为若干组连续的行,被叫做fragment。也即一个streamlet由若干个fragment组成。fragment是数据物理存储管理的最小单位。fragment保存在colossus文件系统中的日志文件内。

fragment的大小按如下方式确定:(1)fragment不能太大,以便存储优化服务能比较快地把WOS转换为ROS (2)fragment不能太小,以免在元信息中创建太多的fragment,加重元信息管理的负担。 当向Fragment中写入数据时,Stream Server会缓存最大2MB的数据再写入。

每个fragment上还带有两个时间戳:creation_timestamp, deletion_timestamp。数据读取请求同样携带着一个快照时间戳snapshot_timestamp,通过比较这三个时间戳,可以判断fragment是否对数据读取请求可见。fragment可见的条件为:creation_timestamp <= snapshot_timestamp < deletion_timestamp

Fragment File Format: 如下图所示,文件头中有一个File Map。File Map列出了相同streamlet中的所有已经写入过的Fragment的信息。文件头中还有一个TrueTime时间戳。当数据写入后,还会在文件尾写入一个布隆过滤器,写入一个定长的文件尾。对于BUFFERED类型的流,在进行flush时,还会向Fragment中记录一个元信息,以保存flush时提交到了哪个row offset。

streamlet和fragment对用户不可见,相关信息记录在Spanner中。

WOS与ROS

WOS:write optimized storage format。当数据通过vortex的写入API进入系统后,首先以这种格式存储。顾名思义,这种格式对写入速度比较友好。

ROS: read optimized storage format。数据被写入一段时间后,会被后台的整理任务整理为ROS格式。ROS的主要由两种,也即capacitor和parquet。

架构

如上图所示,vortex中主要包括stream server, SMS, SOS三个组件。在客户端运行着vortex的client library。

Stream Server

stream server组成vortex的数据平面。stream server负责管理streamlet和fragment的元信息,并通过事务日志和检查点的方式确保上述元信息被持久化。Fragment被存储在colossus上的日志文件中,检查点、事务日志同样也被存储在colossus中。每个borg cluster中常常有上百个stream server。

  • Fragment文件:见上文
  • 日志文件:日志文件中会多保存一份File Map,以便BigQuery读取数据时,能直接通过Stream Server的日志文件确认有哪些fragments要读取

SMS

SMS即stream metadata server。SMS组成vortex的控制平面。SMS管理stream,streamlet、fragment,并将streamlet分配给某一个Stream Server负责处理。

SOS

SOS即Storage Optimization Service。将WOS转为ROS,并将旧数据标记为已删除。SOS以LSM树的方式维护Fragments。首先,SOS将WOS转换为ROS,同时减少Fragment的数量。SOS还会在后台进行自动数据聚簇。

Thick Client Library

之所以叫做厚客户端,是因为vortex的客户端可以绕过SMS直接同stream server交互,并且支持故障重试。

负载均衡和故障恢复

BigQuery的框架中,每个用户的工作负载由一个主borg cluster和一个辅borg cluster负责处理。具体到Vortex的处理逻辑,当用户使用Vortex写入数据时,优先由主borg cluster进行处理。当主borg cluster暂时不可用时,vortex会透明地转移到辅borg cluster上继续处理。

主borg cluster是以table为粒度进行分配的。也就是说,一个table只能有一个主borg cluster负责处理,多个table的负载可以被均衡到多个borg cluster上。一个table的元信息由主borg cluster中的一个SMS负责处理。Google的数据应用程序负载均衡服务Slicer会监控SMS的状态,当SMS不可用时,Slicer会自动将table的管理任务迁移到主borg cluster中的其他SMS上。当某个SMS负载过高时,Slicer同样会执行类似的迁移动作。由于table的元信息由Spanner管理,元信息的一致性可以由Spanner保证。

核心API示例

enum StreamType {
STREAM_TYPE_UNBUFFERED = 0,
STREAM_TYPE_BUFFERED = 1,
STREAM_TYPE_PENDING = 2,
};
CreateStreamOptions options;
options.set_stream_type(STREAM_TYPE_UNBUFFERED);
Stream s = CreateStream(table_name, options);


RowSet row_set;
// Populate row_set from the input data and the schema.
// ...
// Append data to the end of a Stream.
AppendStreamResponse response = AppendStream(s, row_set,
[row_offset]);

Status status = FlushStream(s, row_offset)

std::vector<Stream> streams = GetStreams();
Status status = BatchCommitStreams(streams);

Status status = FinalizeStream(s);

写入流程

大体流程如下:

  • vortex client发送写入请求到SMS
  • SMS找到或创建一个未使用的stream,并确保有一个stream server上已创建该stream的streamlet。
  • SMS告诉客户端streamlet id和stream server的地址。
  • 客户端建立一条到stream server的长连接,以便向streamlet写入数据。

推测的细节如下:
client slicer SMS stream server colossus spanner 本图为推测 CreateStream select a SMS based on load,etc CreateStream select a stream server based on load,etc 返回id,地址给客户端 Create Streamlet data transfer (AppendStream(streamletid)) 何时创建frag? create fragment snappy compress encrypt write frag loop [max buffer 2MB] finish fragment update metadata loop [fragments] flush stream write commit record create new stream let 重复上面的写入过程 FinalizeStream client slicer SMS stream server colossus spanner

备注:默认情况下,Vortex不会应用主键约束。也就是用户可以创建主键,但是Vortex仍然允许主键重复。如果用户希望确保主键的唯一性,用户在写入数据时应该只使用UPSERT,DELETE这两种操作,这样vortex就会按照主键的语义操作数据。

读取流程

推测的读取流程如下:
client bigquery spanner Stream Server colossus select xxx gen_snapshot_time() get_frags() (if ss is online,把ss当成缓存用) get_frags() get_frags() (ROS+WOS) filter frags based on snapshot_time read data in frags until last record client bigquery spanner Stream Server colossus

关键点:BigQuery支持直接从colossus上读取vortex所写入的文件。

总结

Vortex中以下设计值得学习:

  • 面向写入和读取,使用不同的存储格式,从而兼顾写入性能和读取性能
  • 使用thick client library,减轻服务器的压力
  • 写入需要server的,但是读取可以不要server,直接让客户端从分布式存储上读,从而降低存储成本
相关推荐
Linux运维老纪4 分钟前
分布式存储的技术选型之HDFS、Ceph、MinIO对比
大数据·分布式·ceph·hdfs·云原生·云计算·运维开发
DavidSoCool24 分钟前
es 3期 第25节-运用Rollup减少数据存储
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客28 分钟前
使用 Elasticsearch 导航检索增强生成图表
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
Ray.199843 分钟前
Flink在流处理中,为什么还会有窗口的概念呢
大数据·flink
抛砖者43 分钟前
3.Flink中重要API的使用
大数据·flink
金州饿霸1 小时前
Flink运行时架构
大数据·flink
金州饿霸1 小时前
Flink中的时间和窗口
大数据·flink
watersink2 小时前
面试题库笔记
大数据·人工智能·机器学习
数字化综合解决方案提供商2 小时前
【Rate Limiting Advanced插件】赋能AI资源高效分配
大数据·人工智能
Elastic 中国社区官方博客3 小时前
设计新的 Kibana 仪表板布局以支持可折叠部分等
大数据·数据库·elasticsearch·搜索引擎·信息可视化·全文检索·kibana