本文作者杨传辉,花名日照,现任 OceanBase CTO、团队创始成员。本文根据4月28日的直播《下一代分布式数据库一体化设计》内容整理。
大家好,我是杨传辉,上个月和大家讨论了分布式数据库经历的三代演变:第一代 NoSQL 系统,第二代可扩展的 SQL 处理,到下一代透明扩展的企业级数据库。与第二代相比,下一代企业级分布式数据库采用一体化设计,融入经典数据库精细化的设计理念,追求极致性能。本次直播是上次的延续,将介绍下一代企业级分布式数据库的一体化设计。
把稳定的系统做高效,远比把高效的系统做稳定更容易
开始之前,首先穿插一段我对系统设计理念的思考。每个系统设计时都需要考虑架构、稳定性和性能,这三者之间的关系是什么?一个经典的规律是“把稳定的系统做高效,远比把高效的系统做稳定更容易”。
最难的是从 0 到 1 把系统做稳定。有了稳定的系统,接下来逐步优化性能往往会比较顺利,直到遇到系统架构的性能天花板。因此,系统架构设计之前,首先要考虑清楚系统的目标和性能天花板,接着基于正确的架构把系统做稳定,最后优化性能。如果系统的目标是成为世界级的企业级分布式数据库,那么,架构设计之初就必须把追求极致性能作为一个必选项,这将从根本上改变企业级分布式数据库的设计。
回顾一下三代分布式数据库:
为了解决可扩展性和并发处理性能问题,分布式数据库经历了三次迭代:
第一代是分布式存储系统,也称为 NoSQL,2013 年之前比较流行,基本思路是牺牲 SQL,牺牲事务、一致性和企业级功能,只支持简单的 KV 操作从而做到可扩展;
第二代是分布式数据库,以 Google Spanner 系统为代表,支持可扩展的 SQL,在第一代 NoSQL 系统的基础之上引入了 SQL 和分布式事务,保证强一致性,但是不太注重 SQL 兼容性和性价比,单机性能往往比较差;
第三代是透明扩展的企业级数据库,也就是我说的“下一代企业级分布式数据库”。以 OceanBase 为代表。分布式架构对业务透明,支持完备的兼容 MySQL 和 Oracle 的企业级功能,支持 HTAP 混合负载,采用 C 语言实现,单机性能很高,且系统架构的性能天花板很高,可以基于该架构追求极致性能。
企业级分布式数据库除了做好分布式,更要坚守初心
经典数据库包含存储、事务、SQL 这几个核心引擎,以及基于这些核心引擎之上的数据库功能和性能、成本、安全、可靠等企业级特性。企业级分布式数据库在经典数据库的基础之上引入了分布式,实现了高可用和可扩展。虽然分布式数据库在原生分布式架构上产生了很多创新技术,但在数据库的功能、性能、精细化程度上还有一段很长的路要走。
企业级分布式数据库除了做好分布式,更要坚守数据库的初心:提升功能兼容性和单机性能。经典数据库的关键技术经受住了时间的考验,例如 SQL 标准、事务模型,企业级分布式数据库需要向经典数据库学习 SQL 兼容性。今天,分布式领域很热门的一些技术,例如存储计算分离、HTAP,最早也出自经典数据库,且经典数据库在精细化程度上往往做得更好。
存储计算分离
相信今天很多人都听过存储计算分离,但不同系统的做法差别很大。业界有三种存储计算分离方案:
第一种本质是基于中间件分库分表,后端的数据库表示存储,中间件表示计算,这种方案是真正的存储计算分离吗?显然不是,我也把这种方案叫做“伪存储计算分离”;
第二种把系统划分为 SQL、事务和分布式 KV 层,分布式 KV 表示存储,SQL 和事务表示计算,存储和计算采用松耦合设计,这种方案能够解决可扩展的 SQL 处理问题,但每次操作都涉及到计算和存储之间的远程访问,且事务相关元数据存储到分布式 KV 表格中,增加了事务处理的额外开销,牺牲了性能;
第三种采用紧耦合设计,SQL、事务和 KV 表示计算,KV 层数据块依赖的分布式文件系统表示存储。这种方案来自于经典数据库的 IOE 架构,SQL、事务和 KV 层表示计算,底层依赖 EMC 的 SAN 存储。Amazon Aurora 借鉴了经典数据库的存储计算分离架构,并在云原生环境下发扬光大,成为最终的事实标准。
为了追求极致性能,我认为,企业级分布式数据库应该向经典数据库学习原生存储计算分离技术,我推荐第三种方案。
HTAP
HTAP 也是分布式数据库领域的一个热门概念。有两种做法:
第一种是主备库物理隔离,主库做 OLTP,备库做 OLAP,主备之间通过 redo 日志做同步,备库与主库之间有一定的延迟。第二种是在同一套引擎实现 OLTP 和 OLAP 混合负载,区分 OLTP 和 OLAP 请求所在的资源组,对资源组进行逻辑隔离。
第一种方案实现相对简单,但由于产生了更多数据冗余,性价比较低;第二种方案实现相对复杂,但采用一体化设计,性价比更高。第二种方案来自经典数据库,例如 Oracle、SQL Server。
我认为,企业级分布式数据库应该学习 HTAP 技术,采用第二种方案。
极致性能
现代数据库的性能瓶颈往往在 CPU,不在磁盘 IO。为了优化 CPU,经典数据库往往会采用本地化处理:
- 尽量减少跨服务器操作,做到服务器本地化;
- 尽量在同一个线程完成全部 SQL 操作,做到 CPU 核心本地化;
- 尽量将每次访问的数据放在一起命中 CPU 二级缓存,做到 CPU 缓存局部化。
- 在代码层面追求精细化,主要代码采用 C 语言实现,少量关键路径代码甚至采用汇编语言实现,优化每个SQL 算子的 CPU 指令数。手动管理内存,充分利用数据库内存生命周期的特点提升内存利用率,避免语言层面内存自动垃圾回收的额外性能开销。
企业级分布式数据库还应该向经典数据库学习精细化设计,从而获得极致性能。数据库优化到最后往往是抠细节。怎么理解系统设计的天花板?打个比方,如果一个分布式数据库设计之初没有考虑极致性能,那么,无论怎么做,也只能做出对标芯片 28nm 的技术;只有设计之初就把极致性能考虑在内,才可能做出对标芯片 7nm,5nm,甚至 3nm 的技术。当然,7nm,5nm 的技术架构复杂度会远远高于 28nm,前面几年做起来会比较慢,但等到架构稳定之后才会逐步释放技术红利。
企业级分布式数据库的一体化设计
企业级分布式数据库借鉴经典数据库的一体化设计理念,追求极致性能,本质是一个支持动态扩展和无损容灾的 MPP 架构。
在 SQL 层,借鉴企业级数据库,例如 Oracle 的 HTAP 设计,在同一套引擎同时支持 OLTP 和 OLAP 混合负载;在事务层,实现了支持自动容错的分布式事务和多版本并发控制,保证与经典集中式数据库对标的强一致 ACID;在存储层,通过分区级 Paxos 日志同步实现高可用和自动扩展,支持灵活的存储架构,包括本地存储,以及存储计算分离。
当企业级分布式数据库既具备可扩展性,又具备良好的功能兼容性和性价比,并在 TPC-C、TPC-H 等数据库 benchmark 和核心应用场景上都取得突破时,才是名副其实的下一代分布式数据库。
企业级分布式数据库的 Paxos
企业级分布式数据库支持分区级 Paxos 日志同步,通过 Paxos 选举协议实现高可用和自动容错,RPO=0,RTO<30 秒;通过分区级日志同步做到可扩展,支持动态增加服务器提升系统的处理能力,无需人工干预。
2014 年,OceanBase 将 Paxos 协议引入到数据库,首次在金融核心系统做到 RPO=0,也正是依靠这项技术,成为支付宝的最终选择。基于 Paxos 协议,OceanBase 继续研发了同城三机房、两地三中心、三地五中心等多种灵活的容灾部署方案。
经典集中式数据库往往采用主备同步方案,有两种同步模式:第一种是强同步,每个事务操作都需要强同步到备机才可以应答用户,这种方式能够做到服务器故障不丢数据,但必须停服务,无法保证可用性;另外一种是异步,每个事务操作只需要在主机成功就可以应答用户,这种方式能够做到高可用,但主库和备库之间数据不一致,备库切换为主库之后会丢数据。
强一致和高可用作为数据库最重要的两个特性,在主备同步模式下,鱼和熊掌不可兼得。Paxos 是一种基于多数派的分布式投票协议,每个事务需要成功写入超过一半服务器才可以应答用户。俗话说得好,“三个臭皮匠顶过一个诸葛亮”,假设总共有 3 台服务器,每个事务操作要求至少在 2 台服务器上成功,无论任何一台服务器发生故障,系统中还有 1 台包含了全部数据的服务器能够正常工作,从而做到完全不丢数据,并在 30 秒之内选出新的主库恢复服务,RPO 等于 0,RTO 小于 30 秒。所有保证 RPO=0 的协议都是 Paxos 协议或者 Paxos 协议的变种,Raft 协议就是其中之一。
Raft 协议是 Paxos 协议的一种简化,原理是在 Paxos 协议基础上增加了一个限制,要求按顺序投票,也就意味着数据库 redo 日志顺序同步。Raft 协议的好处是实现简单,但每个分区只能顺序同步,并发同步性能较差,在弱网环境下事务卡顿现象概率较高;Paxos 协议支持乱序同步,虽然实现更加复杂,但并发同步性能好,在弱网环境下事务卡顿现象概率较低。Raft 类系统发明了一个概念叫:Multi-Raft,指的是每个分片运行一个 Raft 协议。这个概念和经典的 Multi-Paxos 是不对等的,Multi-Paxos 指的是一个分片内做并发,Multi-Raft 指的是多个分片之间做并发,如果单个分片写入量很大,仍然是会产生性能瓶颈的。
Paxos 和 Raft 两种协议都是合理的做法,我个人建议采用并发性能更高的原生 Paxos 协议,这也是顶尖互联网公司在大规模分布式存储系统的主流做法,包括 Google Spanner,Microsoft Azure,Amazon DynamoDB,OceanBase 等等。
经典数据库往往采用服务器级静态日志流,主库和备库之间只有一个单一的日志流,这种方式一般不支持动态扩容。企业级分布式数据库可扩展性的关键在于采用分区级的动态日志流,从而很自然地实现分区级负载均衡,用于动态扩容。存储计算分离可以借鉴 Oracle 的自动存储管理技术,也就是 ASM 技术,通过统一接口管理本地磁盘和远程分布式存储,每个数据块可以写入本地磁盘,也可以写入远程分布式存储。由于数据块往往可以通过 buffer pool 缓存到 SQL 计算节点,大部分场景能够做到本地化处理,性能较好。这也是 Oracle RAC 系统中采用的方案。
今天参与直播的同学应该有很多从事 DBA 工作,我过去接触过的很多 DBA 都有一个固有的认知:强同步意味着性能大幅降低,例如 Oracle DataGuard 开启强同步之后性能大幅下降。
企业级分布式数据库面向 Paxos 强同步设计,通过异步提交和批量提交(Group Commit)技术规避强同步对系统性能的影响。事务提交写日志任务后立即释放工作线程,释放出来的工作线程可以处理其它并发事务,等到日志强同步成功后再通过异步任务回调应答用户。另外,写日志时可以将多个并发事务的日志合并成一批写入同一个缓冲区并强同步到备机。OceanBase 的实践经验表明,通过各种优化手段,能够将强同步对系统并发性能的损耗减少到 5%~10% 以内。
企业级分布式数据库支持自动容错的分布式事务和多版本并发控制。分布式数据库的难点在于分布式场景下的故障恢复和并发控制,其中,大量代码逻辑都是用于异常处理的。很多同学都有过一个疑惑,分布式数据库不就是单机数据库加上 Sharding,为什么会这么难呢?根本原因在于容错处理和极致性能,导致同步操作变成异步操作,需要给每个操作增加错误处理,且这些问题是耦合在一起的,需要在架构层面统一考虑清楚,任何一个地方出现漏洞都可能导致架构方案推倒重来。
很多场景都会遇到分布式事务的需求,有多种不同的应对方案,中间件 XA 的做法是依赖底层数据库,只要底层数据库持续可用,就能很简单地进行异常处理,不会出现经典的协调者故障导致的阻塞问题;NoSQL 系统的做法是回避一致性和分布式事务,只支持单行事务或者单机事务。
对于企业级分布式数据库,必须直面问题,采用 Paxos 加两阶段提交协议来实现自动容错的分布式事务:
Paxos 协议实现自动容错,两阶段提交协议保证分布式事务的原子性。很多分库分表方案也支持分布式事务,但往往不支持容错,服务器故障时需要人肉处理挂住的分布式事务。这种方案也许能够通过 PoC 测试,但无法大规模应用到生产系统。
两阶段提交协议把事务提交过程分成了 prepare 和 commit 两个阶段,相比经典数据库的事务提交,两阶段提交额外增加了一个阶段。为了避免两阶段提交协议增加事务延迟,可以采用一阶段优化技术。与两阶段提交的经典实现不同,协调者不需要持久化状态,而是在故障恢复时由参与者共同协商。基于这种实现方案,prepare 成功即可应答用户,不需要等到第二轮 commit 成功再应答用户。最终,只有一次写日志延迟和一次 RPC 同步延迟,且写日志与 RPC 同步可以并行起来,追求极致。当然,这种方案增加了故障处理的复杂度。
多版本并发控制来自经典数据库,早期数据库的并发控制往往基于锁来实现,数据库事务的四种隔离级别,例如repeatable read,就是针对锁机制量身定制的。然而,锁机制导致读写互斥,系统并发性能较差。今天,除了IBM DB2 仍然在使用细粒度锁做并发控制之外,其它主流数据库,包括 Oracle、SQL Server、OceanBase 都清一色地采用多版本并发控制,隔离级别为快照隔离(snapshot isolation)。这种方案的好处在于写入操作不影响读取,更适合并发越来越大的分布式数据库。Oracle 今天很成功,除了商业因素之外,几个核心技术选型也非常关键,例如选择多版本并发控制而不是细粒度锁,一体化的 Oracle 集群技术,一体化的混合负载技术。
多版本并发控制有两种比较经典的实现:一种是 MySQL 数据库中使用的 read view,另外一种是 Oracle 等商业数据库中使用的 read version。
其中,read view 方案的事务没有提交版本号,每次读取时需要获取所有正在进行中的事务列表,扩展性比较差;read version 方案的每个事务都有唯一的提交版本号(相当于 Oracle 数据库中的 scn ),每次读取时只需要获取最新的事务版本号即可,扩展性比较好。
企业级分布式数据库采用 read version 方案,每个事务执行过程中的产生的修改都以未提交数据存储在系统中,读取时根据快照版本选择系统中的历史数据,不会见到正在修改的数据,保证事务的原子性。如上图,账户 A 在机器 1,账户 B 在机器 2,账户 A 给账户 B 转账 50,快照读取要么读到转账之前的数据,要么读到转账之后的数据,不会出现读取到一半的情况。
为了获取全局一致的 read version,有两种实现方案:一种方案是经典的全局版本号生成器,另外一种方案是 Google Spanner 系统中采用的 TrueTime。TrueTime 的好处在于支持全球级跨地域可扩展能力,缺点是每个事务额外增加了 7 到 10 毫秒的延迟。企业级分布式数据库应该采用全局版本号生成器的方案,减少事务延迟和应用适配成本。当然,全局版本号生成器本质上是一个单点,需要解决高可用自动容错的问题,以及事务版本号生成的性能问题。
企业级数据库的 HTAP
企业级分布式数据库借鉴经典数据库的 HTAP 技术,实现了同一套引擎同时处理 OLTP 和 OLAP 混合负载。HTAP 并不是全新的技术,以 Oracle 为代表的经典数据库一直都在处理企业客户的混合负载,且精细化程度极高。无论是混合负载,还是存储计算分离,企业级分布式数据库都应该从经典数据库中借鉴经验,坚守数据库的本质,站在巨人的肩膀上做创新。
经典数据库通过行列混合存储支持 HTAP 混合负载,将一个表格划分为行组(row group),每个行组内按列存储,在行存和列存之间寻找一个平衡点。
每个行组都是一个压缩单位,支持智能索引和高效压缩,例如在行组内存储 count、sum 等索引元数据。另外,Oracle 和 SQL Server 都支持 In Memory 列存,OLTP 查询访问磁盘中的行存表,并在内存中额外存储一份列存表专门用于 OLAP 查询。HTAP 往往指的是同时支持 OLTP 业务和实时 OLAP 业务,这里需要避免走极端,
由于 HTAP 采用行列混合存储,对于纯粹的离线 OLAP 业务,性能可能不如更加专用的 OLAP 和大数据系统。HTAP 的价值在于更加简单通用,对于绝大部分中等规模的客户,数据量不会特别大,只需要一套系统即可。当然,对于超大型互联网企业,一套系统肯定是不够的,需要部署多套系统。我们既要不断探寻更加通用的 HTAP 方案,又要避免 one size fit all,最终的方案很可能是 one size fit a bunch。
HTAP 的另外一个技术挑战是资源隔离。
偷懒的做法是多副本做物理隔离,主副本做 OLTP 查询,备副本做 OLAP 查询。另外一种是经典数据库中采用的资源组方案,无论是 Oracle 还是 SQL Server,都支持定义不同的资源组,并限制每个资源组可以使用的物理资源。资源组的隔离可以通过类似 SQL Server 数据库内的 SQLVM 来实现,也可以通过操作系统底层的 cgroup 机制来实现。
数据库业务往往有三类用户:OLTP 用户做在线交易,Batch 用户做批处理,DSS 用户做报表,通过资源组限制每类用户可使用的 CPU、IO、网络资源,从而避免 OLTP 业务受影响。Oracle 最新版本的多租户隔离就是采用cgroup 机制,OceanBase 也采用了类似的机制,实际效果都很不错。
相比 MySQL 等开源数据库,经典商业数据库的最大价值在于能够处理复杂查询和混合负载,企业级分布式数据库应该向经典数据库学习 SQL 优化和 SQL 执行技术。
经典数据库采用基于代价的优化,且支持基于代价的改写,很多分布式数据库的优化器依赖开源的 Calcite 框架,由于通用框架的限制,很难做到基于代价的改写,复杂查询的支持能力有限。Oracle 优化器分成两个阶段:第一个阶段串行优化,第二个阶段并行优化,对分布式和并行场景的考虑相对较少,企业级分布式数据库可以在 Oracle 优化器的基础上做创新,增强分布式和并行能力,支持一阶段优化,在代价模型中同时考虑单机和分布式代价。
经典数据库的 SQL 执行能力也非常出色,无论是 TPC-H、TPC-DS 等 benchmark,还是真实的业务场景,单核执行性能都非常好。企业级分布式数据库应该学习经典数据库的 SQL 执行技术,包括编译执行、向量执行、 push 模型,SIMD 处理、基于结构化数据的强类型系统等等。
企业级分布式数据库 = 经典数据库 + 分布式
最后做一个小结:企业级分布式数据库在经典数据库的基础之上引入了分布式,实现了高可用和可扩展。
企业级分布式数据库除了做好分布式,更要坚守数据库的初心,在功能兼容性、性价比上下功夫。今天,分布式数据库领域流行的一些技术,包括存储计算分离、HTAP,最早都出自经典数据库,且经典数据库经过五十多年的实践,通过应用驱动技术创新做得更加精细。
我认为企业级分布式数据库是未来的大趋势,最终能不能走到那一步,取决于我们能否站在经典数据库这一巨人的肩膀上,深挖经典数据库的核心技术和理念,在消化理解的基础上做创新。企业级分布式数据库在分布式架构上做了很多创新,包括分区级 Paxos 日志同步实现高可用和可扩展,支持容错的分布式事务和多版本并发控制,但对经典数据库的核心技术理解还需要加强,例如深入理解 Oracle 和 SQL Server 等企业级数据库的 HTAP 和存储计算分离技术。
我也借这个机会在这里呼吁分布式数据库领域的从业者更多地向经典数据库借鉴一体化设计理念,做出下一代分布式数据库,坚守数据库的初心。
以上是我的分享,本次分享是《下一代分布式数据库设计思考》的延续,OceanBase 团队后续会持续不断加强技术分享。感谢大家的关注,希望和大家继续讨论分布式数据库的架构设计问题,也期待大家的建议。谢谢!
附《下一代分布式数据库一体化设计》直播观众 QA
为什么 OceanBase 要基于同一套引擎实现 HTAP 呢?
A:经典数据库,比如 Oracle 或者 SQL Server,其实都是在一套引擎下支持 HTAP 混合负载,这种方式做得更精细,性价比更高,且经典数据库通过类似 cgroup 等技术已经解决了 TP 和 AP 隔离的问题。OceanBase 技术上可以更多借鉴发展了五十多年的经典关系数据库。
OceanBase 最新版中对标准 SQL 的支持度是多少?
A:实际应用中,MySQL 业务大部分都能做到平滑迁移,Oracle 模式下基本的 Oracle 功能也都是支持的,基本只需要很少的改动就可以比较平滑地由 Oracle 迁移到 OceanBase。
OceanBase 作为一个以 TP 见长的数据库,AP 计算能力怎么样呢?
A:AP 主要采用行列混合存储、编译执行、向量引擎、基于代价的查询改写和优化等技术,再加上 OceanBase 的可扩展性很好,OceanBase 在 AP 领域里面的实时分析部分是业界领先的。当然,对于离线大数据处理,Spark 等大数据方案可能是更合适的选择。
数据量大概多少 可以使用 OceanBase 做 AP 呢?
A:这个是看业务需求,100G 到 PB级 不设限。AP 是 OceanBase 提供的一个能力,数据量小,可以把并行设置小一些,用的计算资源就小。数据规模大了,给计算资源多一些就好了。本质上并没有一个“量”的限制。AP 的能力,体现在把机器硬件资源充分调动起来的能力,生成高效的并行计划等方面的能力。
OceanBase 的性能和机器数量的关系是什么?
A:可以看看 OceanBase 的 TPC-C 报告,TPC-C 场景 1500 多台机器规模的情况下基本都是线性扩展的。
更多问答,可以在“问答区”和 OceanBase CTO 杨传辉直接互动。