四层解耦的 Serverless | 元数据和事务系统的技术难题和关键设计
引言
自 Snowflake 架构诞生之后,该公司最高市值接近 1000 亿美金,Snowflake 提出的计算、存储和元数据三层分离架构也引领了国内众多厂商的架构设计,我们能够看到:
Hashdata 的 3 层架构:
南大通用 GBase:
doris 2.x 版本的架构,并且已经开源:
该架构核心设计思想大体如下:
把有状态的模块,例如元数据,事务管理,锁管理等,Snowflake 甚至把执行计划缓存,query cache 缓存都放到元数据层,计算和存储都变成无状态的服务,方便对计算和存储做弹性;
作为有状态的服务不太好实现 serverless,为了降低大规模场景下元数据层的成本,都把元数据层做成多租户共享的服务。
在众多厂商尚未明确阐述元数据层独立后所面临的挑战和技术细节的情况下,Relyt AI-ready Data Cloud 作为一个采用四层解耦架构(元数据、计算、缓存和存储)的云原生数据仓库,通过多年的技术沉淀和广泛的客户实践,积累了丰富的经验。本期,我们邀请了质变科技 AI-ready 数据云团队布道师、云原生领域资深人士元飞为大家分享话题《计算、存储和元数据三层分离架构下,元数据和事务系统的挑战和关键技术》。
在上述背景下,应该如何应对元数据层独立后的技术挑战?
保持与 PostgreSQL 生态系统产品的一致体验:我们致力于让客户能够像使用单机版 PostgreSQL 一样便捷地使用云原生数据仓库。虽然开源产品的用户对事务能力的要求不高,但闭源产品通常提供标准的 ACID 事务能力,这已成为闭源产品提升用户体验的关键竞争力之一。
远端存储与本地存储性能差异的解决方案:我们着力解决远端存储与本地存储之间的性能差距,旨在让用户的 DDL 操作和读写过程能够达到与使用本地数据库相同的延迟。特别是在 TPC-H 等场景下,我们实现了高吞吐量和低延迟的性能优化。
元数据管理的挑战:传统大数据的元数据管理相对简单,因为它们主要面向不可变的大文件。我们探讨了元数据层如何应对实时数据仓库中的实时小批量写入,以及高频的 update/delete 操作,还有高 QPS 的点查 Servering 场景。
面向未来的演进:我们探讨了如何向湖仓一体架构演进,实现数据的开放共享,并面向 AI 实现 AI-Ready 的挑战。
元数据层作为数据仓库的核心组成部分,我们将从 Relyt AI-ready Data Cloud 的实践经验出发,深入分析其中的关键设计和技术难题。
架构设计
元数据服务层包括两层:无状态服务层 & 可扩展分布式存储层。
无状态服务层:负责表、列、文件和统计信息的抽象,支持 MVCC 能力,能够提供一致的元数据视图,将 KV 结构封装为表 API,方便多个 DPS 或应用服务的访问,DPS 指代 Relyt 中一组计算资源,与 Snowflake 的 virtual warehouse 是一个概念;
可扩展的分布式存储层:基于 FoundationDB (简称 FDB)作为持久化存储,提供安全、可靠、可扩展的基础存储服务能力。
这样设计的好处在于:
全局一致,多 DPS 统一元数据,update/delete 跨 DPS 实时可见;
极致弹性,服务节点无状态,动态弹缩,性能随节点线性扩展;
安全可靠,fdb 支持 3AZ 部署,实时备份和恢复。
对无状态服务层做进一步展开,其中有下面几个关键服务:
Meta Service:负责表、列、文件和统计信息的抽象,支持 MVCC 能力,能够提供一致的元数据视图,将 KV 结构封装为表 API,方便多个 DPS 或应用服务的访问。
Coordinator:基于 PostgreSQL 提供接入服务,执行计划的生成和执行计划的分发。
Master:负责全局事务管理,事务号分配,活动事务管理,2PC 实现,以及元数据和加锁管理。
FDB:是一个 ordered key-value,并且使用的是 range 分区,为了实现多租户下用户资源的隔离,我们把用户实例 id 作为 key 的前缀,不同的用户通过实例 id 做隔离,实例 id 下面是对应实例的数据。
Table Meta:表的 metadata 信息,包括表的描述,权限,可以参考 PostgreSQL 的 pg_class。
Column Meta:列的信息,可以参考 PostgreSQL 的 pg_attribute
File Meta:文件信息,此外我们还在 key 的编码中加入了文件的过滤信息和 shard 信息,实现了基于 key 前缀的高效过滤。
Delete Bitmap:文件中被删除的行的标记信息,被删除的行通过一个 bit 位来实现标记删除。在我们的列存实现中,采用的是与 Greenplum 类似的标记删除来实现 update 和 delete。
Statistic:供优化器使用的统计信息。
Query cache:参考了 Snowflake 的设计,我们把 query cache 保存在 FDB,实现跨实例和跨用户的高效查询。
这样设计的好处在于:
事务兼容:支持 MVCC,并发写;
PostgreSQL 兼容:Coordinator 基于 PostgreSQL 的插件机制来实现,兼容 PostgreSQL;
Master:把事务管理的负载从 Coordinator 卸载下来,提升了 Coordinator 的事务处理能力,支撑高 TPS 的实时写入和 Servering 场景的高 QPS 查询任务。
关键技术
关键读写流程
client 向 Master 发送 begin 命令,启动事务,在 Master 会开始事务状态机;
Master 把 SQL 和事务信息发送给 Coordinator
Coordinator 从 FDB 读取元数据信息
Coordinator 对 SQL 做解析生成执行计划,
Coordinator 把执行计划下发给 Worker
Worker 根据文件信息从对象存储读取文件,从 FDB 读取 visimap,并执行
Coordinator 把执行结果返回给 Master
Master 执行事务提交,在提交前首先做写写冲突检测,再把 FDB 的元数据做提交。这里我们把 FDB 的元数据分成 temp space 和 work space,其中第第 6 步的写都写入 temp space 自己事务的空间,在提交的时候会"move"到 work space,这个"move"通过 FDB 的事务来保证原子性。
把执行结果返回给客户端。
关键设计:
与大多数数仓的做法不同的是,我们在做写写冲突检测的时候,并没有遇到冲突就把整个事务回滚,原因是当前系统强依赖后台的 vacuum 对数据做合并和重排来提升查询的性能,如果后台的 vaccum 和用户的 update 冲突就回归会降低用户体验,同时 vaccum 和 update 本身都是比较重的操作,会导致我们做大量的无用功。所以这里我们的做法是通过写补偿,把用户的 delete 操作在 vaccum 合并后的文件中重放,实现了“写写并发”。
Insert 时序图
Lock table t:这里就是 PostgreSQL 本身的表级锁,insert/update/delete 拿的是数据表的 2 级锁。
Unlock table t:与上面的 lock table 对应,释放的数据表的 2 级锁。
原子性保证,这个通过 2PC 来解决。
Delete 时序图
这里的核心是如何解决写写冲突的问题。
写写冲突检测
Lock file_visibility table:对修改的表的辅助表加 4 级锁。为了避免在 ww-conflict 中间有其它事务对这个表也在做冲突检测,我们在开始 ww-conflict 之前,需要首先对该表的辅助表加 4 级锁,只允许对辅助表(非数据表)select,不允许对辅助表(非数据表)update/delete/insert,直到事务结束释放。由于是对辅助表加 4 级锁,而不是对数据表加 4 级锁,并不阻塞其它事务的 update/delete/insert(在 update/delete/insert 过程中,与 PG 传统做法不同,不加 2 级锁,只加 1 级锁,因为此时并不会修改 work space 的数据),只会阻塞其它事务 prepare/commit 和冲突检测。
MVCC 实现
我们基本借鉴了 PostgreSQL 本身的 MVCC 算法,在此基础上根据上述数据结构调整。实现了基于 KV 的可见性判断算法:
虽然实现具有一定的复杂性,但是好处是行为保持与 PG 的行为保持一致,降低了 Relyt 的学习成本。
Timetravel 实现
基于上述 MVCC 算法,我们可以很容易实现 Timetravel。
Timetravel 相当于我们去读某个历史时间点的元数据的快照。我们只需要变更读的事务快照,可见性判断读取的是数据的 ts_xmin 和 ts_xmax,基于上述的 MVCC 算法,即可获取 Timetravel 所需版本的元数据。
极致性能优化
GMeta 的 cache 实现
FDB 作为元数据存储的一个优势在于它提供了比较大容量的 kv 存储能力,自动的扩缩容能力,但是在面向大量数据扫描,特别是 visimap 数据扫描的场景,它的压力还是比较大。8w 个 segfile 查询,耗时在 400~500ms 之间,其中 8w 个 segfile 的数据总量在 23MB 左右,但是由于单次 fdb 交互只能拿到 200KB 左右的数据,导致需要 100+次 fdb 的交互才能拿完,网络开销占比较高,如果一次性能拿完 23MB 的数据的话,按照网络带宽计算,大概耗时在 20ms 左右。为了解决这个问题,我们在 FDB 前面构建了元数据缓存服务,叫做 gmeta service,我们把 gmeta service 管理的数据在本地的 rocksdb 保存一份。它的流程如下:
写入流程:
维持现有逻辑,将 segfile 和 visimap 的数据写入到 tmp space 中;
在执行 move 阶段,先将 tmp space 的数据挪动到 work space(此处不再清理 tmp space 下的数据);
在执行 move 阶段最后,将 tmp space 的 txn infor 设置为 Committed 状态,同时向事务提交队列写入一条关于该 gxid 的提交信息;事务提交队列即在 FDB 中单独分配了一段 key 的 range,保存事务的提交状态。
读取流程:
1.刚启动阶段(或 out of sync 阶段):
a.service 获取当前事务提交队列中的最后一条记录,记录其分布式事务 id,gxid;
b.(清理 rocksdb)service 扫描整个 workspace 的 key,写入到本地的 rocksdb 中;
c.为提高可用性,可以在 service 未构建缓存前,提供 fallback 到直接访问 FDB 的模式;
2.client 发起查询请求,请求包含两个信息,一个是事务信息,还有一个是 zdbrelnode+seqno;
a.若 client 本地无缓存,则 ZdbRelNode+seqno 信息为空;
3.service 接收请求,根据事务信息,得到该事务对应的当前的 seqno,计算当前的 seqno 和 seqno 之间的 delta 信息,将这部分 delta 内容返回给 client;
4.client 将最新的 seqno 和 delta 信息缓存在内存中,在下次查询时,使用最新的 seqno 信息;
a.注意,此处需要考虑到 sortkey 的查询,如果做本地缓存了,就没有必要将 sortkey 下推给 gmeta service,而是直接拉全量数据到本地做裁剪;
GC 流程:
在现有 GC 逻辑中,增加对每个 relation 的事务提交队列的清理逻辑,同时需要清理该事务对应的 tmp space 空间;
文件裁剪
数据的裁剪在 OLAP 类型的数据库中是一个重要的优化点,为了更进一步优化性能,我们把文件的 sortkey 编码到了文件名中,在检索文件的时候,实现了直接根据文件名做过滤,减少需要返回的文件数,同时也减少了打开文件再根据文件 meta 信息裁剪的开销。
减少读文件 visimap 请求
对于 OLAP 系统来说,数据写入后较少有修改,所以每个文件都去 GMeta 访问 visimap 是不合理的,特别是在高并发的 AdHot 查询中,高频访问 gmeta 会容易成为系统的瓶颈,所以我们在返回给 worker 的文件的时候,会带上文件是否有 visimap 的标志,读文件的时候如果文件没有 visimap,就无需请求 visimap。
经过上述的优化,在 30TB TPC-H 测试场景下:
查询获取 fileinfo 性能,依靠 gmeta service cache 方案,做到 500ms 以内。
查询获取 visimap 性能。初次总共耗时 600~700ms 已经达到,依靠上述的 gmeta client cache 方案降低并发下网络带宽,一次查询带宽控制在 1GB 左右。
实时化
传统大数据的数据来源大部分是日志,对于 TP 数据库中的数据还是采用 T+1 全量同步的方式,无法满足实时数据大屏,实时运营分析场景下的需求,目前我们实现了 Flink-CDC 插件,支持分钟级的延迟的实时数据写入。对于有更高的 ms 级延迟的实时数据写入,并提供主键去重的能力,我们将在下一篇文章中详细介绍。
湖仓一体
对比湖方案,当前的元数据虽然在大规模数据集的性能上有一定的优化,但是开放性不足,后面我们会实现 spark connector 把当前的元数据和数据直接对 spark 计算引擎开发。
总结
传统大数据从诞生的第一天起,就是存算分离,但是与数据库相比,大数据生态的存算分离在使用场景,无法很好的支持并发的增删改查;用户体验差,没有事务保证,需要用户自己来处理 failover;需要多种产品和技术架构组合,带来使用的复杂性,提高运维成本。与其它数仓产品相比,Relyt 支持“写写并发”,用户的 update/delete 与后台的 vacuum 能够并行,完整的事务 ACID 的能力,以及极致的性能,为客户在离在线一体数仓场景,提供一个更优的选择。
版权声明: 本文为 InfoQ 作者【AI数据云Relyt】的原创文章。
原文链接:【http://xie.infoq.cn/article/7380291de65d4e3a70b9742b7】。文章转载请联系作者。
评论