关于作者:
杨传辉,OceanBase CTO。2010年作为创始成员之一加入 OceanBase 团队,主导了 OceanBase 历次架构设计和技术研发,从无到有实现 OceanBase 在蚂蚁集团全面落地。同时,他也主导了两次 OceanBase TPC-C 测试并打破世界纪录,著有《大规模分布式存储系统:原理与实践》。目前,杨传辉带领 OceanBase 技术团队致力于打造更加开放、灵活、高效、易用的下一代企业级分布式数据库。
2022 年 8 月 10 日,OceanBase 4.0 小鱼在年度发布会亮相,单机分布式一体化架构也正式和大家见面。从我的角度看,OceanBase 总共经历了三次大的架构升级:第一次架构升级是 OceanBase 0.1~0.5 版本(2010 年~2015 年),当时的 OceanBase 通过单写多读架构实现了准分布式,有 UpdateServer、ChunkServer、MergeServer 等多种不同的角色;第二次是 OceanBase 1.0~3.0 版本(2016 年~2022 年),OceanBase 成为一个对等的全分布式架构,所有节点可读可写,逐步支持了完整的 SQL 功能;第三次架构升级就是这次发布的 4.0 版本,我们正式提出了单机分布式一体化架构。
这篇文章主要和大家分享, 4.0 背后的设计理念和技术思考。
面向云设计,以分布式为基石
在过去 70 余年的数据库发展历程中,集中式数据库诞生了 Oracle、SQL Server、MySQL、PostgreSQL 等众多优秀作品,它们在单机性能和 SQL 功能做得非常出色,但是没有办法水平扩展;分布式数据库的出现解决了水平扩展的难题,但是单机性能和 SQL 功能相比集中式数据库有明显差距。这个过程出现很多的分布式数据库,其中有些分布式数据库其实是分布式存储系统,只支持简单的 NoSQL 功能或者有限的 SQL 功能;也有一些分布式数据库同时支持水平扩展和完整的 SQL 功能,这些系统常常被称为 NewSQL,例如 CockroachDB,Google Spanner,但是,它们的单节点性能都不到 MySQL 的 1/3。
因此,单机和分布式如何选择成为最让人纠结难以选择的问题,通常的做法是根据数据量来做:如果数据量比较小,选择功能完备的集中式数据库;如果数据量很大,则选择分布式数据库或者分布式存储系统,牺牲功能和单机性能,通过修改业务或者堆机器来解决。
对于分布式数据库,有不同的理念:很多人或者很多系统认为分布式是数据库的一种补充,适合某些数据量特别大或者并发量特别高的细分领域,而我的观点是不同的:我认为分布式是未来面向云的下一代数据库的基石,未来云数据库的底层都是原生分布式。
打个比方,云数据库就像是电动车,而分布式就是其中的电池技术,有了分布式之后,虽然数据库的基本用法和之前差别不大,但用户体验开始分化,我们已经看到零配置、Serverless 等理念逐步融入到最新的云数据库中。这就有点像电动车,当电池效率提升,充电桩逐步普及之后,电动车开始在用户体验上拉开与燃油车之间的差距。很多人对特斯拉最大的感受并不是所谓的自动驾驶,而是操作简单,踩油门加速,收油门减速,甚至都可以做到不需要刹车。刚开始还有点不适应,但是过一段时间很快会发现这才是汽车本来应该的样子。分布式和云原生也应该是数据库本来应该的样子,未来的主流数据库默认都会具备面向云的灵活性、简单性和开放性,包括:
1) 面向云的灵活性: 具备任意扩展,支持按需扩展存储容量和计算能力,支持按需付费(Pay as you go)。支持客户从小到大全生命周期的数据库需求,当客户业务量很小时,可以选择很小规格的独立实例(比如 4C8G)、甚至共享实例或者按请求付费(Serverless);当业务量逐步增加时,能够很灵活地增加数据库的存储和计算能力;当业务量跨过洪峰回归常规时,能够很平滑地按照需求动态缩容来降低成本。
2) 面向云的简单性: 无论是功能,还是运维,让用户少做选择甚至不做选择。尽可能由数据库完成数据自动分片、自动容错、跨服务器分布式事务等操作,兼容 MySQL/Oracle/PostgreSQL 等用户接口。支持 HTAP 混合负载,提升查询优化和自适应处理能力,尽可能减少用户配置。
3) 面向云的开放性: 以单一“云原生”,到客户为中心的多云原生,减少 IaaS 层依赖。支持“一库多云”、“一库多芯”,能够按业务需要快速高效适配新的云平台和 CPU 等新硬件。
为此,我们提出了 OceanBase 4.0 单机分布式一体化理念,让分布式成为数据库的基石而不仅仅应用到可扩展这一细分场景。为了达成这个目标,我们既要扩展性,也要完整的 SQL 功能和极致的单机性能,从小到大支持用户全生命周期的业务。由于单机分布式一体化架构将入门门槛降低到与集中式数据库基本相当,且在面向云的高可用、可扩展、性价比上具备明显优势,我认为,该架构会逐步成为主流,并且发展出一个与 MySQL、PostgreSQL 平行且同等量级的开源社区。因此,我们决定从 OceanBase 4.0 开始把开源分支和商业分支统一成为一个分支,加快开源社区的发展。
必须攻克的难关:动态日志流融合单机分布式
单机分布式一体化架构要求兼具分布式的扩展性和集中式数据库的功能和单机性能。事务的 ACID( Atomicity,Consistency,Isolation,Durability)是数据库的基本要求,而分布式数据库的难点就在于如何在异常场景下保证事务的 ACID,核心就是如何基于重做日志(Redo log)实现故障恢复,以及基于重做日志实现异常场景下分布式事务的原子性。
我们首先看看业内的已有方案:
A) 服务器级静态日志流: 典型的代表是基于中间件+开源数据库(MySQL/PostgreSQL)分库分表的方案。数据库区分主库和备库,主库将重做日志同步到备库。这种方案不支持分区级的细粒度迁移复制,也就无法实现在线水平扩展。当需要扩容时,往往采用按倍数扩容的方案,且扩容过程会影响业务,由 DBA 手动执行。
B) 分区级静态日志流: 典型的代表是 CockroachDB/TiDB 代表的 NewSQL 数据库,以及 OceanBase 1.0~3.0 版本。每个数据分区/数据分片有单独的日志流,支持分区级的细粒度迁移复制,支持水平扩展。这种方案的问题在于分布式开销与分区的数量成正比,单台服务器支持的表格数量有上限,即使业务的数据可以全部放到一台服务器上,也需要承受分布式相关的 overhead。
C) 日志与数据分离: 典型的代表是 FoundationDB 数据库。将存储服务器和日志服务器分离开来,写事务只写日志服务器,存储服务器会定期从日志服务器拉取日志并应用到本地从而服务读请求。这种方式的问题在于存储服务器上的数据有很短的延迟,影响读取最新数据的效率。
方案 A 的好处在于避免了分布式 overhead,单机性能更好,但是无法实现在线水平扩展;方案 B 的好处在于支持在线水平扩展,但引入了分布式 overhead,会造成额外性能开销;方案 C 的好处在于部署灵活,但会影响读取性能。因此,从 OceanBase 4.0 版本开始,通过动态日志流将方案 A 和方案 B 融合起来,兼具单机性能和分布式的水平扩展能力。 当系统处于稳定状态时,动态日志流类似方案A,每台服务器只有固定数量的日志流;但与方案 A 不同的是,OceanBase 4.0 支持将一个分区从一个日志流迁移到另外一个日志流,这意味着可以实现与方案 B 类似的分区级在线水平扩展能力。这个看似不难理解的方案,但实现起来却极具挑战,举三个实际的场景:
第一,当一个分区从一个日志流迁移到另外一个日志流时,如何确保迁移过程是原子的,也就是说,无论发生任何异常,该分区的所有的副本要么全部迁移成功,要么全部迁移失败;
第二,分区迁移时,如何确保不会影响正在进行中的事务,我们必须考虑到这种情况,有些事务可能做到一半或者该事务正在运行的SQL语句做到一半 ;
第三,分区迁移时,如何确保下游总是订阅到正确的数据,无论什么情况发生,不会丢失也不会重复;
OceanBase 4.0 解决了这些技术难题,实现了在线水平扩展的同时不增加分布式相关 overhead,从而能够像集中式数据库一样部署在小规格的服务器上,做到单节点性能达到甚至超越集中式数据库的水平。
为多云架构而生:从云原生,到多云原生
云计算从诞生之初到现在经历了多次技术迭代,从最早的托管虚拟机,到托管服务,再到今天的多云和 Serverless,不断追求灵活、简单、开放。OceanBase 4.0 正是为多云架构设计的。
灵活:内置自动水平扩展
云上用户从小到大发展过程中,从共享实例,到小规格实例,到大规模实例,再到最后的分布式方案。OceanBase 通过内置的多租户隔离架构,能够实现共享实例,从而尽可能降低成本。 当用户的业务量越来越大时,通过单机分布式一体化架构,可以逐步从小规格实例扩展到分布式实例,小规格实例没有分布式相关 overhead,分布式实例既能扩展存储容量,也能扩展计算能力。支持 Pay as you go 的计费模式,既支持快速扩容,也支持快速缩容。
我们还将探索 Serverless 方案,从而实现按请求付费。Serverless 方案涉及到几个重要的技术点:
- 当用户完全没有请求时,数据库能否做到零消耗?
- 如何快速弹性扩缩容,当计算节点发生故障时,如何快速拉起新的计算节点继续提供服务,做到秒级甚至更低?
- 如何衡量不同 SQL 请求的开销,从而实现按请求计费?有些 SQL 可能很简单,有些 SQL 可能很复杂且需要访问大量数据。
这些问题都很有意思,也欢迎大家和我们讨论。
简单:HTAP = OLTP+
OceanBase 4.0 希望降低数据库选型和运维的复杂度,尽可能用一套数据库满足不同场景的需求。一方面,单机和分布式的架构差异可以通过前面提到的动态日志流方案统一起来;另一方面,我们看到市面上大部分 NoSQL、NewSQL 以及OLAP 系统底层的存储引擎都是类 LSM Tree 架构,可以在一套系统中实现 OLTP、实时 OLAP、Key-Value、JSON、GIS 等多种数据模型的处理,避免用户因为基础设施能力不足而采用多套系统。
我并不支持"One Size Fit All",单机分布式一体化架构也不是万能的,但是,我认为,在不怎么牺牲性能成本的前提下"One Size Fit Bunch"。按照这个思路,我在前一段时间写了一篇文章《真正的 HTAP 对用户和开发者意味着什么》:我认为的 HTAP 其实就是 OLTP+,先有高性能的 OLTP,然后在 OLTP 的基础上支持实时分析,并增加 Key-Value、JSON、GIS 等多模支持,适合在线查询和在线分析业务,对于离线分析和大数据分析并不是最优的。
开放:面向多云的存储计算分离
OceanBase 早期版本支持本地部署,后来逐步支持阿里云和 AWS 等多云部署,存储计算分离是云数据库的标配,有两种设计思路:
第一种,数据库内部实现存储计算分离。 具体做法是将数据库区分为 SQL 层和 KV 层, SQL 层无状态用来做计算,KV 层用来做存储。这种方式的好处是实现简单,可以把可扩展和高可用等分布式特性下移到 KV 层,事务处理构建在一个可扩展、高可用的分布式 KV 之上;当然,问题也非常的显著,这个方案牺牲了性能和开放性,每次 SQL 操作都需要一次 RPC 交互且需要首先将外部数据导入到数据库中。
第二种,数据库与文件层之间做存储计算分离。 具体做法是抛开 SQL 和 KV 分层方案,数据库读写数据块时支持本地或者远程的各种分布式文件系统,数据库用来做计算,文件层用来做存储。这种方式最大的难点是需要将高可用和可扩展的处理融入到分布式事务,实现复杂,好处是保证了性能和开放性,数据库内部的 SQL 和 KV 模块之间不再需要 RPC 交互,且能够适配多云平台上的各种存储系统。
OceanBase 4.0 选择了第二种方案,我称之为“开放的存储计算分离”。 另外,为了更好地适配不同云平台,OceanBase 在设计存储格式时降低了对外部文件系统的依赖。OceanBase 存储引擎是类 LSM Tree 格式,将 SSTable 划分为 2MB 大小的宏块,LSM Tree 引擎执行 Compaction 操作时,只有修改过的 2MB 宏块才需要被重写。每次写宏块操作都是异步的,选择 2MB 宏块大小也能够很好地发挥不同云平台上各种分布式文件系统的性能。
通过这种方式,可以降低对底层存储系统的依赖,用户可按实际业务需求,将数据库部署到不同的云平台甚至多云,并确保系统稳定和高性能。
小就是大:为规模化而战
我认为未来单机分布式一体化领域会发展出一个与 MySQL、PostgreSQL 同等规模的技术社区,这类系统也会有百万量级的企业用户。按照“二八原理”,大部分用户的数据一台机器就能放下,但用户也有快速发展业务的需求,一体化架构能够很好地解决这个矛盾。分布式数据库的复杂度肯定是远高于集中式数据库的,一体化架构能够在用户规模还小的时候将使用门槛降低到集中式数据库的水平,同时,不需要提前担心业务发展带来的扩展性问题,一次选择终身受用。为了扩大使用规模,需要:
第一,支持单机部署和小规格部署。 OceanBase 有一个很有意思的设计:每个分布式系统都会有一个总控节点,用于全局管理调度。OceanBase 的总控节点并不是一个单独的进程,而是一个服务 RootService,集成到 OBServer 里面。这个设计方案的好处就在于单节点部署只有一个进程,且能够在线增加 OBServer,既实现了单节点最低配置,又实现了单机和分布式架构的统一。OceanBase 4.0 将部署规格降低到 4C8G,且未来还会进一步降低。
第二,兼容集中式数据库的行为和使用方式。 作为一个全新的自研数据库,OceanBase 到今天为止仍然坚持兼容 MySQL 和 Oracle 的技术路线,原则上不创造新的使用语法。我们希望能够支持业务平滑迁移,基本不修改业务代码即可由集中式数据库迁移过来。OceanBase 3.x 已经支持了存储过程、触发器、外键、XA 等功能,OceanBase 4.0 进一步增强了对通用 DDL、表锁、通用 LOB、GIS、JSON 等功能支持。
第三,走完全开源的技术路线。 2021 年 6 月 1 日我们宣布正式开源,当时开源分支和商业分支还是两个不同的代码分支,由 OceanBase 研发团队定期将商业分支的代码 patch 到开源分支。这种方式导致 OceanBase 开源分支总是会落后商业分支一段时间,而 OceanBase 4.0 之后我们更进一步,把开源分支和商业分支合并成一个代码分支,使得二者完全同步。
稳定可靠是第一要素:追求极致性能和极致高可用
数据库作为基础软件,需要满足看得见的、看不见的很多需求,例如稳定可靠、性能、成本、高可用、SQL 支持、易用性,等等。从 OceanBase 的技术理念角度看,首先必须确保稳定可靠,所有其它需求都必须为之让步。例如,OceanBase 系统内部有一个数据校验机制,自动对多个副本之间进行实时的事务一致性校验和定期的基线数据一致性校验,为了实现该校验功能,会牺牲一些性能,且对存储格式的设计方案有一定约束,但这是必须要做的,稳定可靠是我们为客户坚守的第一要素,也是 OceanBase 数据库最基本最朴素的第一原则。
数据库本质的东西还是跑得有多快,成本做到多低。只有追求极致性能的数据库才可以应用到核心场景。数据库的性能相当于芯片的制程,有的数据库性能差,相当于是 28nm 技术,也能应用在一些模拟芯片的场景,有些数据库性能好,相当于是 7nm 技术,能够应用在所有场景,包括对性能要求很高的手机等。
OceanBase 4.0 使用 C++ 语言,但我们不允许使用 C++ 语言的高级功能(包括C++ STL),只使用 C++ class 等基础功能用于组织代码。我们在数据库内部管理所有的内存和 IO 使用,而不是交给底层的操作系统。为了优化性能,我们需要优化每个算子,尽可能减少每条 SQL 语句执行过程中的 CPU 指令数。对于一个分布式数据库,往往还会遇到如下性能挑战:
- 主备强同步。强同步会增加事务提交的延迟,如果让 SQL 执行线程等待强同步返回,将会带来大量的线程上下文切换开销。OceanBase 的做法是异步化,SQL 执行线程提交同步任务后立即处理下一条 SQL 语句,等到强同步成功后再通过回调函数应答客户端。
- 类 LSM Tree 查询性能。类 LSM Tree 引擎读取时需要合并磁盘中的 SSTable 和内存中的 MemTable,这个操作会影响查询性能,涉及到 Compaction 策略,查询算子的设计,等等,需要不断优化。
- 跨服务器操作性能。这里面既涉及到分布式事务,也涉及到 SQL 语句远程执行的性能,需要将 SQL 执行尽可能本地化,并不断优化远程执行的效率。
OceanBase 从 0.5 版本开始就将 Paxos 融入到数据库中实现无损容灾,今天,OceanBase 首创的“RPO=0,RTO < 30秒“已经成为数据库行业高可用的事实标准。当然,30 秒之内恢复(RTO < 30 秒)并不是绝对的,取决于大量分区 Paxos 选举的租约时间和改选时间。
随着 OceanBase 4.0 进入单机分布式一体化架构,再加上我们进一步优化 Paxos 选举协议及全面探活机制,最终能够做到 RTO < 8秒,给业务带来更强的的持续可用力。 从 30 秒到 8 秒,这短短 22 秒的提升看似简单,但背后非常复杂。举一个例子,F1 方程式比赛中有一个必须的环节就是换胎,这个过程是争分夺秒的。从 1950 年代需要分钟级到现在最快记录 1.92 秒。数据库的运行就像持续运行的赛车比赛,RTO 就像中间的换胎环节必须争分夺秒。而我们更难的地方在于 F1 的换胎环节是提前规划,一个 10 多人的团队来完成的。但数据库的故障是任何时间都可能发生,且完全不需要人工参与。
写在最后:与用户和开发者共同成长
这次 OceanBase 发布会的 4.0 小鱼通过动态日志流实现了单机分布式一体化架构,支持单机小规格部署,在现场演练的环节我们看到,在同等硬件环境下,OceanBase 4.0 单机 sysbench 基准测试性能好于 MySQL。同时,4.0 版本也具备面向多云的灵活、简单、开放,以及规模化输出的能力。当然,每个版本走向成熟都离不开大量真实业务场景的打磨,Serverless 和 HTAP 等特性也在不断完善过程中。
OceanBase 4.0 的很多创新和想法来源于用户的需求或者建议,我们也会一直坚持 MySQL 模式完全开源的策略,和我们的用户、开发者一起,把单机分布式一体化架构真正做成数据库的主流,发展出一个与 MySQL、PostgreSQL 同等规模的一体化数据库产品和社区。