2022 年 12 月 14 日~16 日,由 IT168 联合旗下 ITPUB、ChinaUnix 两大技术社区主办的第 13 届中国数据库技术大会(DTCC 2022)在线上隆重召开。大会以“数据智能 价值创新”为主题,上百位技术领袖齐聚云端,进行多维度、多视角、多层级的交流碰撞,为广大数据领域从业人士提供一场年度技术盛宴。
OceanBase 首席架构师杨志丰(花名:竹翁),在主论坛带来题为《OceanBase 4.0:单机分布式一体化的技术演进》的演讲,和业内分享 OceanBase 从 0.5 版本到 4.0 版本的技术架构发展与演变。
以下为 OceanBase 首席架构师杨志丰在 DTCC 2022 上的发言实录。
大家好,我是 OceanBase 的杨志丰,今天和大家分享的题目是《OceanBase 4.0:单机分布式一体化的技术演进》,主要内容更加偏向技术解读,探讨架构演进的同时,会与大家分享 OceanBase 对于单机分布式一体化架构的理解和思考。
在今年 8 月 10 日 OceanBase 年度发布会上,我们正式发布了 OceanBase 4.0 小鱼,这个版本有一个形象的比喻叫做“小就是大”, 我们希望通过这个版本架构的变化,使得 OceanBase 可以从原来支持大型企业为主,真正走向中小型企业。 用户可以使用一个 OceanBase 数据库,在企业或业务发展的不同阶段都能使用单个数据库,不用做迁移。我今天将从技术的视角去分享一下这背后技术的原理是如何思考的。
OceanBase 从 2010 年开始研发,下面是 OceanBase 0.5 版本的整体架构图,彼时 OceanBase 分成存储和计算两层。上一层是无状态提供 SQL 服务的服务层,下一层是由两种 server 共同组成的存储集群。
这样的架构能够使 OceanBase 比较好的支撑类似于淘宝收藏夹的业务,具有一定的扩展性,特别是读的扩展性比较强,并且 SQL 层是无状态的,可以自由的伸缩。
但同时,这个架构面临最主要的问题是由于写入的节点为 UpdateServer 节点,其是单点写入、多点读的架构,会导致在更大规模并发要求下,没有办法进行扩展。
仅从这幅图上还有一个不容易被意识到的问题:我们发现以这样一个方式去割裂存储层和 SQL 层之后会有一个很大的问题,查询时延不好控制。实际上网络服务很难控制时延,会有一些抖动,如果对时延要求极高情况下,很难控制时延抖动。
为了解决上述问题,OceanBase 摒弃之前的架构,发展出了 OceanBase1.0 - 3.0 的架构,整体上来说是一个完全对等的节点,所有的节点都可以在处理 SQL 的同时,处理事务并保存数据。在这幅示意图中,纵向方向是分布式可扩展层,横向方向是复制层。横向方向提供服务高可用能力,纵向是通过不断加机器去提升整个服务的扩展性。
演进到 4.0 版本之前,原有的架构已经有了非常好的扩展性。在这一扩展性下,我们用 3.0 版本参加了 TPC-C 测试,OceanBase 是当时唯一一个通过了 TPC-C 测试的分布式数据库,也是唯一一个通过 TPC-C 测试的国产数据库,而且到目前为止保持世界第一。
这也反映出 OceanBase 3.0 架构在水平扩展性上有非常好的适应性,如图可以看到,从三个节点到 OceanBase 打榜拿到了 7.07 亿 tpmC 指标的情况下,随着节点数增加,整个tpmC指标有非常好的线性扩展性。参加 TPC-C 评测时,OceanBase 通过 1557 台机器组成的大集群,在压测 8 个小时之内,每秒钟有 2000 万次事务处理能力。这个结果说明,前面的架构是能支撑非常好的扩展性,几乎这一扩展性和并发处理能力是可以满足绝大多数当前世界上在线服务系统需求的。
但随着业务需求的迭代,我们还是发展出了 4.0 架构,OceanBase 4.0 架构核心的变化,是引入动态日志流的概念。原来把事务扩展和存储扩展的粒度等同起来一起去看,但如果存储分成了若干个分片,导致事务处理和高可用能力也是以这样的分片为粒度的。我们在 4.0 版本里把这两个概念进行了解耦,所以若干个存储的分片会共享一个事务日志流以及这个日志流所对应后面的高可用服务。
这一变化背后最核心的思路,是我们希望能够支撑更小的规模下的一些应用。比如蚂蚁这样大规模应用里,3.0 架构不会遇到瓶颈问题,但随着 OceanBase 走向通用,特别是各种各样的中小企业时,如果日志流的数目和分区数绑定到一起的话,在很多场景下是不能适应对中小规模企业支撑的。也就是说,如果日志流特别多,在越小规模下开销显得就会越大。
基于此,我们有必要从以下几个方面对单机分布式一体化的概念进行解释:
OceanBase 单机分布式一体化数据库体系结构
OceanBase SQL 引擎的单机分布式一体化
OceanBase 事务处理的单机分布式一体化
OceanBase 单机的性能扩展性实验
4.0 架构既可以通过分布式方式使用 OceanBase 数据库,也可以用大家原来熟悉的类似 MySQL 单机方式使用 OceanBase。
第一,如果以单机方式部署 OceanBase,或者在 OceanBase 集群内部署单容器租户,都能提供原来使用单机数据库一样的效率和性能。
第二,如果使用分布式模式,在租户层面上、事务层面上以及单条 SQL 执行层面上,都不需要因为引入了分布式而付出额外代价。在这种情况下,需要我们在 SQL 层、存储层、事务层各层设计上,以一种单机分布式一体化设计的方式去满足各种情况,在各个层面上做到兼顾。
在数据库发展的阶段有一个争论:数据库应该是基于无共享的集群去设计,还是使用 shared-everything 架构去设计数据库,才能够提供最好的效率?
现在实际的集群,从物理集群角度来看,既不是完全 shared-everything,也不是完全 shared-nothing。在每个机器节点上去看单个节点,也是多处理器的结构,很多 CPU,现在有 96 核机器,甚至更大规格的机器,内存也是越来越大,使用非常高速系统内的总线去和磁盘、和所有外部设备去做交互,并且有很好的网络。所以现实使用的集群不能简单看作是 shared-nothing,就是单机内有非常强的计算和存储的处理能力,为什么不利用这样的能力呢?这也是单机数据库或集中数据库所有的 scale-up 的方向。分布式数据库不应该只考虑水平的扩展,而不去考虑垂直扩展的问题。
如果想利用硬件垂直扩展能力的话,数据库应该怎么做?可以设想一下有这样一种分布式数据库,以下方左图为例,这是现在很多分布式数据库的实际架构图,有点像 OceanBase 0.5 的结构,有专门的计算节点和存储节点。计算节点是一层,存储节点是另外一层,这两层做了单独抽象,它们中间会通过 GTM/TSO 处理全局事务的模块,做多机交互时也需要和这个模块做交互。
如果把这一分布式数据库以非常简单的方式塞到了一个节点上,让它以单机的方式去运行,这里最大的问题是什么?就是这些组件之间的交互在单机内工作时开销非常大,这种开销本质上对于 MySQL 这样的单机数据库是额外的非必要开销,所以显然这样一种简单的方式是很难以和单机数据库相比的。
如果在单机内来看,单机内要有完全独立的单机 SQL、事务和存储三层,相对另外一种方式是所谓的分布式数据库会把分布式 SQL 引擎、分布式事务引擎和分布式存储引擎也看作是独立的三层。我们希望同时去糅合单机这三种引擎和分布式这三种引擎,使用同一套代码,甚至可以动态地去做变换和交互。
OceanBase所认为单机分布式一体化DB架构
除此之外,所谓单机数据库,要在单机内充分发挥扩展性能力,需要在 SQL 层提供并行执行的能力,需要在事务层去提供类似 MVCC 的扩展性核心技术,并且使用类似组提交的技术,使得单机内多个事务也可以并发去执行。在存储层,需要能够支撑单机并行的 IO,当单机内增加更多磁盘和存储带宽时,可以能够充分利用。
分布式内的单机数据库,不能简单把分布式的扩展性做好就行了,即使是以分布式方式去部署时,单机效率也必须是非常高的,需要能够高效去支持串行的执行,高效的执行在分布式事务的情况下,使得单机事务能够有自适应的优化。
对 OceanBase 来说,还独创引入了一个创新技术——单机 LSM-Tree 存储引擎。如果以单机设计的视角去看的话,确实只能做前后台可能会互相影响的合并操作,但我们不是一个单机数据库,如果真正是分布式部署的话,又可以引入一种分布式策略,使得多个副本之间可以做错峰轮转的合并。所以在整体设计上,在 SQL 层、事务层和存储层里,我们每一层的设计都是兼顾了单机和分布式的场景,使得它在单机和分布式场景下都没有多余额外的开销,这是我们的设计目标。
这样我们就要求有 2 个基本特性:
第一,在单机情况下工作时,OceanBase 没有额外其他的组件,就是一个单进程就可以工作,没有多余进程之间复杂的交互。在单进程、多线程模型下,各个组件实际上都是使用简单的函数调用就可以完成交互,这是非常关键的一点。
第二,所有的组件之间既在图里有纵向的交互,也就是 SQL 层、事务层、存储层。如果在单机内就用函数调用的方式去做交互;如果在节点之间,在必要时必须要有节点之间的交互时,才通过 RPC 去交互。
相应于前面所讲的 shared-nothing 和 shared-everything 结合的架构,实际上在每个 OBserver 节点内部,SQL 和事务存储之间都使用函数调用直接去交互的,这和单机数据库是一样的,当我们要在多节点之间交互时,也会打破所谓严格的去做分层的,选择最优的、最合适的、效率最高的方案。
例如,一个节点的 SQL 向另外一个节点上的 SQL 层发一个消息,让这个 SQL 层再去访问它的存储节点,这里最优的取决于你要做什么,不同的负载下面可能有不同的选择,OceanBase 可以直接访问一个远程存储。在事务处理层也是如此,如果单机事务下不需要和别人去做交互,就不需要和其他的事务组件进行交互。
OceanBase 执行引擎,要处理很多情况,为什么要做这么多细分呢?是因为希望在每种情况下都能自适应做到最优。大的层面上来说,每一条 SQL 的执行都有两种模式:串行执行或并行执行。
在串行执行时,如果这个表或者这个分区是位于本机的,这条路线和本机 SQL 的处理、单机 SQL 的处理是没有任何区别的。如果所访问的是另外一台节点上的数据,有两种做法:把数据远程拉取到本机来,叫做远程数据获取服务。远程执行,如果单个事务内所访问的数据都位于另外一个节点上,会把整个事务处理和存储访问过程全部发送到另外一个节点上,将整个事务提交全部代理给它,然后再返回来;如果单条 SQL 访问的数据位于很多个节点上,可以把计算压到每个节点上,并且为了能够达到串行执行(在单机情况下开销最小)的效果,还会提供分布式执行能力,即把计算压给每个节点,让它在本机做处理,最后做汇总,并行度只有1,不会因为这个而增加资源额外的消耗。如果是并行执行,支持并行查询,对并行查询分本机的并行和分布式并行,同时支持 DML 写入操作的并行。
对于串行的执行,一般开销最小。这种执行计划,在单机做串行的扫描,既没有上下文切换,也没有远程数据的访问,是非常高效的。对于当前很多小规模业务来说,串行执行的处理方式足够。但如果需要访问大量数据时,可以在 OceanBase 单机内引入并行能力,目前,这个能力很多开源的单机数据库还不支持,但只要有足够多的 CPU,是可以通过并行的方式使得单条 SQL 处理能力线性地缩短时间。只要有一个高性能多核服务器增加并行就可以了。
针对同样形式的分布式执行计划,可以让它在多机上分布式去做并行,这样可以支撑更大的规模,突破单机 CPU 的数目,去做更大规模的并行,比如从几百核到几千核的能力。
针对串行执行有两种执行方式:DAS 执行和分布式执行。
DAS 执行,方式之一是拉数据,如果数据位于远程,并且是简单的点查询或索引访问回表查询,这种方式资源消耗是最小的,我们会把这个数据拉取到本地,它的执行计划和本地的执行计划从形式上、形状上是没有区别的,在执行器里会自动去做这个动作。但有时候把数据拉过来,不如把计算压下去,所以我们同时支持了分布式执行,需要强调的是这种分布式执行并没有额外增加资源的消耗,我们会保证它的并行度和前面 DAS 执行是一样的。
对于某些特定的查询或大规模扫描,我们会动态自适应选择这两者,基于代价去评估哪种执行效果最好。
并行执行框架可以自适应处理单机内并行和分布式并行,它们是同一套框架。这里所有并行处理的 Worker 既可以是本机上多个线程,也可以是位于很多个节点上的线程,我们在分布式执行框架里有一层自适应数据的传输层,对于单机内的并行,传输层会自动把线程之间的数据交互转换成内存拷贝。这样把不同的两种场景完全由数据传输层抽象掉了,实际上并行执行引擎对于单机内的并行和分布式并行,在调度层的实现上是没有区别的。
既然做扩展性更难的是事务处理,那么事务处理过程中为什么要兼顾单机和分布式?我们从下图开始解释:
左图是传统的分布式事务处理过程,分成事务的开启阶段和事务的提交阶段,右图是 OceanBase 的事务处理过程。
OceanBase 事务提交协议提出一个新思路,叫做参与者既协调者的两阶段提交协议。OceanBase 两阶段提交比起左图,从提交事务到提交成功这个时间之内,我们所处理的消息量和写入的日志量比左边这幅图少很多,这使得整个两阶段提交的时延有很大的优势,这个优势也会支撑我们后面要讲的即使是在 OceanBase 分布式场景下,事务的处理能力也不会像很多其他的分布式数据库一样开销非常大。
如果单个事务只涉及到单个日志流,一般来说如果业务数据量在负载均衡能够容忍的粒度之内,日志流不需要特别多,很大概率上,完全以单机方式去部署时,只有一个日志流,而一个日志流内任何的事务是不需要走两阶段提交的。
事务不能独立地去看,在一个分布式系统里可能既有涉及到多日志流的事务,也有涉及到单日志流的事务。两者之间是有关系的,对于单日志流事务来说,OceanBase 引入了独创的优化,使得 OceanBase 单日志流事务的处理过程中,不需要去访问全局的时间服务,只需要访问本地特有的时间服务,同时保证全局的一致性。
如果抛开分布式事务提交的协议来看,所有的事务以及整个工作负载都没有分布式事务的话,整个事务处理过程和单机数据库是相当的。
下面的实验以三个节点的方式,也就是说节点和节点之间是副本的关系,实际上事务处理是单机完成的,就把它看作是单机,OceanBase 随着硬件性能的增强扩展性实验,从 4 核到 64 核,可以做到基本线性扩展的。从 90000、180000、370000、690000、1200000。在 64 核规模范围之内,OceanBase 可以提供线性的扩展。
大家对分布式数据库有一个误解,或者很多分布式数据库可能给大家形成一个固有的印象:原来某单机数据库或集中式数据库,可以用一台机器支撑一个业务,引入分布式数据库以后,扩展性好了,但如果想支持同样的并发量,可能不得不使用三个节点共同来提供服务,才能达到单机同样的性能和效率。
这显然不是用户所希望的分布式数据库。关键问题在于看性能时,不光要看吞吐量的增加,还要看单个 SQL 或单个事务从应用视角来看多快能处理完,因为事务处理从单个部分来看,我们希望实现的是随着分布式事务比例的增加,时延是在增加的,但是关键有两点:即使是由完全的分布式事务组成,时延也需要足够低;以及当单机事务没那么多的时候,请不要买一赠一,给我赠送额外时延。
第一,SQL 层、存储层、事务层,即使在分布式场景下,也需要为单机粒度的事务和 SQL 做优化。
第二,如果三个组件之间完全做了独立的分层,实际上用户是缺乏控制手段的,能不能不要发一个 RPC 去访问一个数据,如何能放到一个节点上省掉这些 RPC。所以我们希望能够让用户和 DBA 在非常极致性能要求下有这样一个控制的能力。好比 OceanBase 为什么要用 C++ 去实现,就希望能充分控制内存,控制所有时延的消耗。可以把一个事情能够做精确的控制,可控性非常重要。同样我们分区的能力也需要能够控制的,比如通过提供 Table-group,能够使得表之间没有分布式事务开销的。
如图,如果没有分布式事务场景下,以分布式情况下部署,单机效果到底怎么样?OceanBase 4.0 和 MySQL 8.0 企业版在同样硬件情况下做了对比,在硬件 32 核规格下,黄色是 OceanBase,从数据上可以看到,OceanBase 4.0 在相同硬件环境下性能优于 MySQL,即使是小规模场景下,也可以放心地使用 OceanBase 分布式数据库。
使用以后有什么好处?
传统使用 MySQL 主备库的方式有一个很明显的问题,就是容灾时会丢数据,这个问题无法解决,而 OceanBase 首先肯定可以做三机高可用,从 4.0 以后正式会推荐大家一种部署方式——每个 ZONE 里就有一个 OceanBase 的节点,叫做单机三副本,没有太多额外的开销。OBProxy 层提供了业务连接不断的能力,如果不需要这样的能力,可以像使用 MySQL 一样不需要部署 OBProxy,就可以达到比 MySQL 更好的高可用的能力。
比如最开始是完全单机部署,业务做一些原型实验就够了。随着业务规模扩大,对于计算和存储的要求越来越高过程中,可以把这一节点做垂直的扩展,原来是 4 核,现在变成 16 核,如果在云上买,可以在 ECS 上直接申请提升规格,OceanBase 是可以充分利用所有增加的 CPU,提供一个更好的性能。
另外一个维度是,如果现在不需要高可用能力,不想付出三个节点的成本,那么主备库就够了,OceanBase 同样可以提供主备库能力,这种高可用能力也是和传统的数据库相当的,主备库也是我们的一个选项。
如果高可用能力要求越来越高,可以使用三节点。后面可能随着业务的发展或企业规模的扩大,可以进化成一个完整形态的 OceanBase 分布式数据库。更关键的是,这样一个形态的变换或扩展,里面每一个箭头都可以反方向去做,每一个箭头的变换都是动态生效的,不需要去替换 OceanBase 二进制,都可以全功能地在三种形态下使用,去做动态的变换。
我们在设计 OceanBase 单机分布式一体化架构时,思考了一个问题。大家从使用 MySQL 到使用 OceanBase 有一个不适应的地方:OceanBase 有多租户的能力,大家进来需要创建一个租户,后来我们和用户、客户做了很多讨论,最后确定多租户的特性即使是在单机情况下也是要保留的,特别是私有化部署和公有云部署时。
如果在私有化情况下去部署,很多小企业可能不想去部署复杂服务器的环节,但现在买不到一核机器,有最小规格的硬件也有很多核,这种情况下如果不需要其他额外基础设施的话,OceanBase 的原生多租户能力,可以把一个机器切成很多个数据库来使用,无须额外的容器管理的系统。
对于大规格来说,OceanBase 部署后可以做非常灵活的垂直伸缩。对于分布式不言而喻,如果在分布式场景下,更是可以有垂直扩展和水平扩展两个方向的能力,并且这种能力是以租户为单位的。一个租户是 4 核×3 个容器,另外一个机器希望以单机方式运行,可以直接给它 16 核,或者不希望做分布式,都是可以的,此时,多租户提供了一个可管理的粒度。
对于公有云的部署,或者希望在你的企业里一个OceanBase 大集群,就更有价值了。即使是小规格,比如一个 OceanBase 的 server 通过 16 核方式启动起来,但希望有一个更小力度的租户,比如 0.5 核的租户。在数据库内部,OceanBase 是可以支持 0.5 核租户的,帮助用户更加精细的控制成本,可以在云上做租户内垂直扩展,也可以租户间负载均衡,这两个维度都可以去做弹性、自由伸缩。
在不同的形态下,我们都保留了 OceanBase 所有的功能以及多租户的能力。
对用户来说,OceanBase 单机分布式一体化能力,有两个维度的价值和意义:
第一,OceanBase 既可以单机方式部署,提供单机数据库相当的能力,并且可以在任何时刻,管理员可以去做形态的变换,由一个单机的形态变成分布式形态,从分布式形态变回单机形态,都可以做动态变换的。
第二,即使是在分布式部署场景下,相较于其他分层的分布式数据库,OceanBase 的性能有很大的优势,如果用户做精细控制的话,单机事务比例增加以后,效率和单机数据库也是相当的。
我的分享就到这里,感谢大家对 OceanBase 的关注。谢谢大家!