likes
comments
collection
share

祝贺DB和OS有情人终成眷属

作者站长头像
站长
· 阅读数 5

首先祝贺DBOS = DB + OS 喜结连理,长长久久,白头偕老!

DBOS的概念首次出现在2022年的VLDB会议上。接着,在2023年,几位论文作者共同创办了一家公司来对其商业化。最近的进展是,该公司在两周前完成了850万美元的融资,并推出了其商业产品DBOS Cloud 。

DBOS的论文作者包括图灵奖得主Michael Stonebraker和Spark创始人Matei Zaharia。除此之外,论文的作者还有开创了learned index的Tim Kraska,以及为现代数据库优化器和执行器技术奠定基础的Goetz Graefe。DBOS专注于云端的多机环境,指出了当前操作系统加上K8S在管理和编程方面存在的一些问题,提出了在事务型数据库基础之上,重构一个针对集群,面向Serverless/FaaS服务的操作系统的构想。

DBOS论文在数据库的部分着墨不多。DB3Kernel是一个新开发的数据库内核,作为其开发工程师,我们将主要从数据库内核的视角出发,探讨支持DBOS所需的关键能力。

趋势层面:DB和OS以前恋爱过,这次会长长久久

DB和OS的分分和和确实有着悠久的历史。我考古了一下,Pick操作系统是一个早期的例子,它在1965年就已经将DB的概念引入到OS中。还有这篇论文(图) -- 最有喜感的是里面这个[156]引用是DBOS作者Michael Stonebraker 1981年写的 “Operating system support for database management”一文。

祝贺DB和OS有情人终成眷属

近一点的例子就是微软的WinFS项目:它试图通过集成SQL Server进OS来改进Windows。这不仅能支持OS内各类搜索,而且还利用SQL Server提供的事务来管理OS的状态,并对外提供了具有事务语义的API。遗憾的是,WinFs项目在2006年宣布搁置。比尔·盖茨将WinFS项目视为他对微软的最大失望之一,认为这是一个超越时代的尝试。从工程师的角度,我想有当时需求、软件技术、硬件限制的各种约束导致它的失败:同时期Oracle在$8M的机器上跑出世界第一的TPCC,大约每分钟3百万个事务。而今天DB3Kernel在一台PC机上,纯内存非等待模式下,PL/SQL编写的TPCC接近每秒1百万个事务了 – 虽然不能完全等价比较,但说明今天软硬件技术发展早已突破了当年的限制。

从需求方面看,云计算解放了OS的定义:这里的OS是一个广义上的概念,意味着只要包含了任务调度、任务间通信、文件系统等支持,就可以被视为一个操作系统。对于DBOS所认同和希望改进的Serverless/FaaS应用而言,这样广义上的操作系统已经足够应对需求。另外一方面,AI有能力将大量半结构化、非结构化数据解析为结构化数据(Vector等) -- 有多少非结构化数据就有多少结构化数据 -- 这就更进一步的强调了DB在未来世界中的角色。

所以,OS定义的放松,DB在未来的重要性和技术的进步,硬件方面内存、I/O和网络性能的显著提升,让我们处于技术变革中 -  这应该就是盖茨先生说的超越时代的那个时代吧。DBOS的提出正是基于这样一个背景,这让我们相信DB和OS这次的世纪大婚会长长久久。

DBOS将状态数据委托给DB进行管理,这有诸多优势。(1)它简化了OS的内部实现,使得OS的各种操作变成了SQL编程。由于处于事务保证下,减少了考虑并发正确性的负担。我们在后面文件系统的讨论中可以看到一个例子。(2)由于OS和APP的状态信息都集中存储,所以它能为所有节点提供一个一致的全局视图,也为APP提供一个云原生数据库。当所有信息集中时,这就让分析、调试、迁移以及恢复等操作变得更加一致和简化。而基于数据库实现的文件系统很好的解决了 K8S一直以来让大家诟病的有状态POD的管理问题。(3)DBOS提供了受数据库事务保护的SDK。类似OS内部实现,用户在使用这些SDK开发应用时,减少并发正确性的考虑。已经发布的DBOS服务提供涉及状态管理的高层API,如SQL事务、幂等性操作、工作流等等。从用户视角,DBOS可被视为是K8S、数据库、分布式存储、Lambda以及软件事务内存(Software Transactional Memory)的升级合体。

实现层面:一切皆为表,应作如是观

Unix的一个哲学概念就是一切皆为文件,它将各种I/O设备、数据流等抽象为文件,通过统一的接口进行操作,简化了系统设计和编程模型。DBOS的作者认为现在需要改为一切皆为表(everything is table)。文件和表都是容器,其根本区别在于后者是有模式(schema)的,因此可以使用事务和SQL来处理。这个理念实际上有很多现实的实现:

-          C#/LINQ(Rust/iter(),C++/ranges)将容器当做表

-          Spark的核心概念DataFrame概念上等价为表

-          PowerShell把命令的输出格式化为表,因此可以更好的实现命令管道

-          提供类SQL命令的git工具、shell、control platform等等

在这里,我们不深究“表”是否严格意义上的符合第一范式的二维,因为现实世界中的关系型数据库模型已经放宽了这一限制。例如,引入了扩展类型如增加的数据/向量类型、JSON类型等,这些都是对二维模型的扩展。通过让表的少数列支持这些扩展类型,不仅增强了数据的表达能力,而且并未引入过多的复杂性。因此,我们更倾向于将这种模型称为2.x维。

基于这个理念,DBOS的communicator服务(就是send/recv)其实等价于INSERT/SELECT;而DBOS的Idempotency服务(幂等性)的支持就是增加一个“done bool”的表列就可以了,等等。所以DBOS将核心构建在数据库之上大大简化了它的功能实现。

数据库层面:要怎样共襄盛举

显然DB是DBOS的核心技术支持。论文中虽然没有明确提出对数据库的各种要求,但我们这里通过对使用场景的分析来推断出一些必要的能力。

坚实可靠性( resilience

是DBOS的首要要求。由于OS和应用程序的状态都存储在DB内部,因此DB的几个9直接影响OS的可靠性。在这方面,可靠性包括(1)快速无损的故障恢复能力是必须的;(2)查询其实也有类似的要求。即使是小查询,我们在下面的任务调度就可以看到一个例子。(3)在系统正常运行时,还需要支持无阻塞的数据库操作,比如在线DDL(online and offloaded) (4)在节点内资源紧张的时候,需要表现出资源不足的平滑容忍。 例如当节点内资源不足时,数据库内核需要以优雅的方式处理,逐步降低性能,支持处处可微的性能曲线;在节点级资源调整的时候,支持在线扩缩容操作;(5)在系统升级期间,实现不降级的滚动升级;(6)安全性是可靠性的一个重要方面,细粒度的权限控制是确保系统安全性的一个关键。

ACID 的事务支持

这个是基础。DBOS将OS内部和应用的状态都集中存放在数据库中。这些存储和访问都是以事务为基本单位进行的。

这里贴一段论文中任务调度的代码:

schedule_simple(P, TID) {
select worker_id,unused_capacity from Worker
  where unused_capacity>0 and p_key=P
  limit 1;
if worker_id not None:
  WID = worker_id[0];
  UC = unused_capacity[0];
  update Worker set unused_capacity = UC - 1
     where worker_id=WID and p_key=P;
  insert into Task (P, TID, WID,...);
}

对于一个任务调度系统,使用了一个SELECT、一个UPDATE和一个INSERT,共计3个SQL语句。在单机环境下,任务调度可能并不一定要使用表来操作,也可以使用一些传统的数据结构来实现。然而,在DBOS面对集群系统时,情况就不同了,因为这些表存储着多个节点的信息。在这种情况下,使用表来进行操作反而更简单。可以将这种做法看作是K8S使用etcd存储各个节点信息进行调度的数据库版实现:

1.       估算需要的性能:我们知道一个SQL语句需要经历parse, analyze, planning到最后执行。普通OS大约2-5us的调度时间,也就是6K-15K个CPU Cycles(假设3G CPU)。如果数据库内核追求极限性能(例如JIT PL/SQL 语句为内存场景优化等),即使有索引维护和再增加一些SQL语句,也可以匹配这个时间。这里需要关注的是是否日志的问题,也就是ACID中的D。日志持久化的延迟,先不考虑云存储复制的毫秒级的延迟,即使本地SSD都需要50us的时间。也许RDMA one-sided write之类的内存复制技术(3-5us)可以帮助,但是最好的方式是也许这里设计上放松对持久性的要求。

2.       更广泛的性能场景:按照DBOS已经发布的服务看,可以预见到DB需要支持极速DML:包括插入(支持communicator和logging服务)、删除(communicator清理)、更新(各种profiler状态更新)和随机读取(普遍的场景)等。在分布式数据库上,可能需要提供多种一致性级别来满足的功能和性能的平衡。

3.       另外一个并发的问题:当两个schedule_simple()同时运行时,第一个SELECT语句可能选到同样的worker,第二个UPDATE语句的写-写冲突检测会导致其中一个事务回滚。这个正确性固然是保证了,但是会给用户奇怪的感觉 – 操作系统不喜欢失败。事务自动重试是一个可选的解决方式。

数据库层的架构问题

DBOS论文直接说的是需要分布式的数据库。但实际上,数据库内核架构的选择和数据库功能、容量以及可靠性都有关。以DBOS的文件系统设计为例:

localized_file (f_name, f_owner, block_no, bytes, f_size, p_key)

1.       容量考虑:文件系统表的每行记录对应一个数据块,大约100个字节(不算bytes,另外存储)。假如DBOS管理1P空间,那一个数据块1M,那么需要10亿条记录,也就是100G空间。单机管的住 – 但如果是10P或者更大呢?还没有算。这可能就需要数据库分而治之了,可能是自行分片(sharding),也可能是分布式数据库。自行分片通常被认为是一种落后的技术,但是如果应用也是足够松散 – 比如用户应用的状态数据,这种方式倒也可以匹配上。

我们考虑两个操作:

1) DBOS文件系统 vs. 普通文件系统的读路径对比(下图):DBOS的一个读需要发起一个SELECT … FROM localized_file语句,经过SQL runtime后进行数据库的index lookup,找到对应的bytes,最后再从本地文件系统中进行block lookup将bytes读出。SQL runtime和FS block lookup可以采用JIT和raw partition的技术将时间降至最低。所以,最后是DBOS 的数据库索引vs., 普通文件系统块索引的对决。

祝贺DB和OS有情人终成眷属

2) 迁移一个节点的数据:有了事务的保驾护航,我们逻辑上很容易迁移一个节点的数据,就是将某个节点的数据INSERT到新的节点,然后DELETE老的数据,获得locality。这个过程中,如果有别的操作读取或者写入该节点数据,事务会保护我们。但是也有若干挑战:(i)这可能是个巨型事务;(ii)如果有隔离级别导致的冲突,谁回滚呢?所以,分布式文件系统可能是一个有挑战的地方。

2.       架构选择:数据库的三个基本架构(SE, SD, SN)都可以做到坚实可靠性,但是难度有区别。DBOS选择SN架构的分布式数据库,因为它的扩展性最好:SN架构节点间交换的是控制,而SD架构节点建交换的是数据 – 而数据的量是远远大于控制的。现代的数据库内核因为有了云存储或者类云存储(例如minIO)这样的大后台,也会混合SE+SDSN+SD,借力存储的几乎无限容量和可靠性,获得更简化和健壮的实现。

3.       异构数据库:管理某些普通表MySQL、PostgreSQL功能上都可以。可是用户应用可能有其他的需求,性能、功能、兼容性等等,可能需要多种不同的数据库来支持。那么如果允许其它数据库的存在,DBOS层面上需要针对性提供匹配的SLA。

复杂查询和流查询的能力

虽然DBOS论文只提到OLTP型的数据库,但是由于所有状态都存储在表中,因此分析能力是不可或缺的。基本的聚合函数、连接操作和窗口函数都是必要的工具。数据库应该提供一个层次化的监控视图,涉及tasks,workers,permissions,files等等,提供给OS和应用程序来观测各种状态。这些视图的查询都涉及到复制查询的优化能力。

流查询在DBOS中也是自然而然的需求,因为操作系统的数据时刻在更新,需要流查询的能力来维护监控视图等。例如,大家熟悉的任务管理器中CPU使用率和IO情况的持续变化就需要流查询来实现。

在DBOS系统中,环形缓冲区(ring-buffer)、对外输出的追踪信息(traces)以及数据库日志,均构成了重要的数据流来源。基于这些数据流,DBOS中形成了一种永久性的流监控视图,它忠实地记录着系统的活动脉搏,随时待命以供用户查询。面临着诸如节点级故障等各种挑战,这些数据流查询功能需要能够从故障中恢复。

数据库内核工程化能力

DBOS是一个意义广大的探索性项目,随着项目的深入,会对数据库内核提出各种特殊的需求。这就需要数据库内核能够快速的修改做出反应。最小 化复杂性是现代化数据库内核的一个承诺。从干净的状态开始,通过精简的设计以及数据库、编程语言、开源和环境的进步,它站在巨人肩膀上,同时摆脱了众多传统的冗余。它使用显著减小的代码库实现了对等的功能、质量和卓越的性能。这种简洁性对于支持DBOS有着至关重要的影响。

理想的数据库是一个时间和需求的函数,所以内核的扩展能力不可或缺。以PostgreSQL的extension方式为例,它非常好的支持了很多扩展增多内核的能力。但是它可能很难支持需要修改parser,扩展algebraizer等SQL方言类的能力。因为受C语言限制,查询树节点类型需要编译时已知,这就给动态扩展树节点类型造成困难。而支持动态发配(dynamic dispatching)的语言这个场景的扩展性就没有问题。

按照前面的讨论,DBOS的数据库层可能有多个不同的数据库,而DBOS或许会采用类似挂载文件系统的方式来支持挂载不同的数据库。但在DBOS开发过程中,始终会有针对优化的数据库,特别是OS自己使用的数据库。因此,实际上可能只有少数获得优先级,受到推荐 -- 这也就意味着数据库厂商将面临DBOS的考试。

最后,再次祝贺DB和OS喜结连理,长长久久!

参考

1.       DBOS的研究网站:dbos-project.github.io/

2.       DBOS的商业网站:www.dbos.dev/

3.       天下观查:mp.weixin.qq.com/s/XvvJ7f7Li…