技术解读 | OceanBase 高并发场景下的性能保障

本文摘自《OceanBase社区版在泛互场景的应用案例研究》电子书,点击链接获取完整版内容。
作者:高山岩,OceanBase 资深技术专家
海量数据日益增长的今天,越来越多的业务系统面临高并发、高性能访问的压力,以至于企业对业务系统的性能保障诉求越来越强烈。数据库系统作为业务系统的基础组件,具备高并发、高性能的能力,是支撑业务系统、满足客户诉求的关键。本文通过阐述数据库组件的设计,解读做好系统性能保障的关键因素。
通过内核组件的合理设计,保障系统性能
作为连续 12 年保障“天猫双 11”大促活动以及用于支付宝核心系统的数据库,OceanBase 久经高并发场景的多重性能考验。2025 年 3 月,OceanBase 性能再次升级,在同等的硬件规模下(16 核配置),经过 Sysbench 标准测试集的实际测试(见图 1),其单机版在整体性能(包括查询、批量读取、写入、读写混合、插入和更新操作)方面全面优于 MySQL 8.0。特别是在高并发写入场景中,吞吐量实现了显著提升,最高提升达到 214.99%,能够满足高负载场景下的业务需求。

图 1 Sysbench 性能基准测试对比(OceanBase 单机版 VS MySQL 8.0)
OceanBase 的高性能离不开系统内核各个组件的设计与实现,主要包含高效的计划管理、并发控制、多维度缓存优化、热点行优化、日志聚合优化和编译优化等方面。下文将分别解析各模块,为大家揭开高性能的神秘面纱。
(一)高效的计划管理
1.计划缓存。
SQL 语句的优化是一个比较耗时的过程,随着 SQL 语句的复杂度增高,优化的时间也会越来越长。为了避免反复执行优化过程,生成的执行计划会加入计划缓存中,以便再次执行该 SQL 时使用。每一个租户在每一台 server 上都有一个独立的计划缓存,用以缓存在此 server 上处理过的 SQL 计划。
在应用系统中,同一条 SQL 每次执行可能会使用不同的参数,为了减少计划缓存的大小,系统会首先将用户 SQL 的参数做参数化处理,得到与具体参数无关的 SQL 字符串,并使用该字符串作为计划缓存的键值。计划缓存是一个典型的 Key-Value 结构,Key 就是参数化后的 SQL 字符串,Value 就是该条 SQL 所对应的执行计划。在 OceanBase 的计划缓存中,SQL 的执行计划可以分为本地计划、远程计划和分布式计划三种类型。在计划缓存中,同一条 SQL 根据其需要访问的数据不同,可能同时有这三种执行计划。对于某一条 SQL 的某一种执行计划,默认情况下 OceanBase 只会保留一个计划,该计划由第一次执行 SQL 时生成;但在某些情况下,同一条 SQL 的参数值可能会影响到计划的选择,计划缓存可能会根据需要,为不同的参数值保留不同的执行计划,从而保证每次执行时可以使用最合适的计划。
2.快速参数化。
有了计划缓存之后,如何快速获取缓存数据,是需要考虑的另一个问题。传统数据库在进行参数化时一般是对语法树进行参数化,然后使用参数化后的语法树作为键值在 Plan Cache 中获取计划,而 OceanBase 使用的是词法分析,对文本串直接参数化后作为 Plan Cache 的键值,因此叫做快速参数化。具体流程如图 2 所示。

图 2 基于快速参数化的获取执行计划过程
计划缓存的优化,减少了计划生成的重复动作。快速参数化,省去了语法分析的过程,与此同时,相比对参数化后语法树做 Hash 和比较操作,对文本串进行 Hash 和 MemCmp 操作,效率更高,提升了从计划缓存中获取计划的效率。两个优化本质上均降低了 CPU 的开销,从而提升系统的吞吐能力。
(二)并发控制
1.数据管理。
OceanBase 存储引擎采用的是 LSM tree 架构,数据分成静态和动态数据。动态数据保存在 Memtable 中并定期 dump 到磁盘中,Memtable 采用 B+tree 以及 Hash 双索引结构对数据进行存储,其中 B+tree 用于范围查询,Hash 用于单行查询。B+tree 的叶子节点保存了行数据的元信息,关键的 3 个字段:主键、锁以及链表指针,如图 3 所示。

图 3 memtable 内存数据结构图(行上的多次修改)
锁信息表示是否有事务持有行锁,事务在修改数据之前需要先加行锁。
链表信息指向多个版本的数据,每个版本只保存增量信息,比如某一次修改只修改一个字段,增量信息只会记录该字段的变化情况。
对于尚未提交,已经转储到静态数据中的行,静态数据会进行特殊标记,用于行锁存在与否的判断。
2.并发控制。
OceanBase 基于 MVCC 和行上的互斥锁,实现了并发控制,主要特点如下:
快照版本一个时间戳,通过比较时间戳的大小就可以确定事务的可见性。因此,相比其他数据库系统,OceanBase 不需要维护全局事务管理器,高并发场景下,不存在全局事务管理器访问瓶颈的问题。
OceanBase 行的元数据上保存了锁信息,同样也不需要额外的锁管理器。
读操不加行锁,写操作加行上的互斥锁,做到了读、写不相互阻塞,提升了高并发场景下的吞吐。

图 4 memtable 内存数据结构图(读写请求逻辑)
(三)多维度缓存
上文提到,OceanBase 存储引擎采用的是 LSM tree 架构,其存储引擎整体架构如图 5 所示。

图 5 OceanBase 存储引擎架构图
通常来讲,LSM 架构的查询,需要将静态数据和动态数据做 merge,经过投影之后再返回给客户端。对于多级的 sstable,这无疑会增加执行路径。为了提升查询效率,OceanBase 设计多级缓存策略,具体包括以下 5 项。
(1)Block Cache:类似于 Oracle 的 Buffer Cache,缓存具体的数据块,实际上 Block Cache 中缓存是解压后的微块,大小是变长的。
(2)Block Index Cache:缓存微块的索引,类似于 Btree 的中间层,在数据结构上和 Block Cache 有一些区别,由于中间层通常不大,Block Index Cache 的命中率通常都比较高。
(3)BloomFilter Cache:BloomFilter 是一种结构,可以帮助加速对空查询的过滤,有助于提升 insert 的性能。OceanBase 的 BloomFilter 是构建在宏块上的,按需自动构建,当一个宏块上的空查次数超过某个阈值时,就会自动构建 BloomFilter,并将 BloomFilter 放入 Cache。
(4)Row Cache:Row Cache 缓存具体的数据行,在进行 Get/MultiGet 查询时,可能会将对应查到的数据行放入 Row Cache,这样在进行热点行的查询时,就可以极大地提升查询性能。
(5)Fuse Row Cache:跟 row cache 的差异在于,fuse row cache 缓存的是当前系统中动、静态数据 merge 之后的值,对于高频的数据访问,可以直接访问 fuse row cache;
(四)热点行优化
随着在线交易、电商行业的发展,业务系统的热点并发压力逐渐成为一种挑战。热点账户短时间内余额大量更新,或者热门商品在营销活动中限时抢购,都是这种场景的直接体现。热点更新的本质是短时间内对数据库中的同一行数据的某些字段值进行高并发的修改(余额,库存等),这其中的瓶颈主要在于关系型数据库为了保持事务一致性,对数据行的更新都需要经过 “加锁->更新->写日志提交->释放锁” 的过程,而这个过程实质上是串行的。因此,提高热点行更新能力的关键在于如何尽可能缩短持有锁的时间。为了缓解热点行更新的问题,OceanBase 提出了提前解行锁(Early Lock Release)的优化方案,其原理见图 6。

图 6 提前解行锁原理
1.优化前。
在用户发起 COMMIT 操作后,数据库(DB)端会触发日志的持久化流程。这个过程包括以下 4 个步骤:
(1)将内存中的数据序列化并提交给本地的 Log buffer。
(2)数据库将日志数据发送到所有备机。
(3)等待多数备机同步日志成功后,数据库才认为日志持久化成功。
(4)最终解锁事务,并向客户端返回事务提交成功的应答。
在此流程中,一个事务的持锁时间包含以下几个部分:数据写入、日志序列化、同步备机的网络通信、日志刷盘的时间。对于三地五中心部署或者磁盘性能较差的情况,持锁时间较长,容易对热点行产生显著的性能影响。
2.优化后。
在数据库优化方案中,整体提交流程基本保持不变,但对解锁时机进行了调整。在新的流程中,当日志序列化完成并提交给 Log buffer 后,立即触发解锁操作,而不再等待多数备机的日志刷盘完成。这样可以有效减少事务的持锁时间。事务解锁后,允许后续事务对同一行进行操作,实现了多个事务并发更新同一行的效果,从而提升了系统的吞吐量。
该优化生效的前提是 OceanBase 内核保证了以下关键特性:
提前解锁的事务如果最终发生了回滚,后续凡是读到该事务信息的事务都需要回滚,我们称之为级联回滚;
提前解锁的事务尚未应答客户端之前,后续凡是读到该事务信息的事务,都不能提前应答客户端;
只支持单机事务使用 ELR 优化,降低级联回滚的概率。
3.优化效果。
基于上述优化方案,热点行场景下的性能可以通过以下公式计算: 𝑇𝑃𝑆=1/{一个事务内热点行的持锁耗时}, 其中,持锁耗时指的是从加锁开始到事务提交完成的时间间隔。
在三地五中心的场景下,由于 SQL 的整体执行耗时为 30ms,事务的 COMMIT 响应时间(RT)约为 30ms。通过该优化,性能基本能够与同城部署保持一致。
基于 Sysbench 单行更新,16c/64g 阿里云 ECS 环境做压测,热点行优化效果见表 1。
表 1 热点行优化效果
(五)日志聚合优化
数据库系统中,WAL 落盘是一个常见的动作。大量、高频的小数据量日志频繁落盘,会产生大量的 I/O,进而影响业务请求 RT 和系统的吞吐能力。为了解决或者优化该问题,数据库领域常见的解决方案是聚合提交,简言之,将多条日志进行聚合,整体执行一次 I/O。高并发写入场景下,降低持久化日志的 IOPS 和与该动作相关的 CPU 开销,最终达到提升系统吞吐的效果。
OceanBase 4.x 版本在 3.x 版本日志聚合方案基础上,重新做了设计,降低了单条日志数据 buffer 拷贝的次数,以日志流的维度,进一步提升了日志聚合能力,架构如图 7 所示。

图 7 OceanBase 日志引擎主、备副本逻辑管理结构
在图 7 中,事务模块提交日志到 GroupBuffer 中做聚合,通过一定的聚合策略,将生成的日志提交给 ringbuffer 实现的滑动窗口,即 FixedSlidingWindow。该结构负责将聚合之后的日志同步备机,触发事务模块日志回调,推高本地最大连续 committed lsn 等信息。
为了满足不同并发写入场景下日志的同步效率,OceanBase 4.x 版本支持两种日志聚合策略:周期性和反馈式聚合。
周期性聚合:后台每隔 1ms 由一个独立的线程触发日志聚合,该策略对高并发持续写入比较友好。
反馈式聚合:对于低并发写入场景,周期性聚合导致事务日志存在 1ms 的延迟,业务影响较大。为了更好地解决该问题,OceanBase 4.x 版本支持 I/O 线程的反馈式聚合策略,即日志的刷盘线程完成当前 I/O 动作之后,主动触发一次日志聚合,进行下一次 I/O 动作。
上述两种策略是互斥的,系统会根据当前的写入流量自适应做选择,兼顾了低并发下单个 commit 请求的延迟和高并发下系统整体的吞吐能力。基于 32c * 3 三副本环境,客户端单次模拟提交日志大小 512B,对比了 OceanBase 日志模块 Palf、Etcd、Braft 三款系统的持久化日志的极限吞吐能力。经过验证,相同并发下,OceanBase 的日志模块 Palf 吞吐远高于其他两个系统(见图 8)。

图 8 OceanBase PALF、Etcd、Braft 三款系统日志持久化极限能力对比
(六)编译优化
2024 年 OceanBase 基于国产化和 Intel 芯片做了大量的性能优化,这些优化目前已经应用于实际的业务场景,并取得了显著的性能提升。
PGO(Profile Guided Optimization)也被成为 FDO(Feedback Directed Optimization),是一类基于反馈式编译优化的技术。其核心原理是基于生产环境中的实际流量采集 profile 数据,经过加工处理,获取热点函数、分支执行频率结果信息,最后将将结果文件输入编译、链接器,重新编译,产生优化之后二进制文件。该优化从多个方面提升了指令执行的效率(icache、itlb、page fault 等)。
LTO(Link Time Optimization),即链接时优化,是另一种编译器优化技术。它允许编译器在链接阶段进行跨编译单元的全局优化,可以完成全局视角的 inline、virtual method 优化,从而达到提升 CPU icache 命中率,进而提升系统的整体吞吐。
除了编译优化之外,OceanBase 通过汇编指令的优化,解决了 ARM CPU 下 glibc 原生 load128 原子操作性能瓶颈的问题;根据 CPU 架构的差异,自适应设置 CACHE ALIGN 的大小,从而实现了 x86 和 ARM cpu 下,热点变量的自适应对齐能力,从而有效减少了 false sharing 的问题。 此优化显著提升了 OceanBase 在国产芯片环境下的运行性能,为各行业信创推广实施中降低了实施成本。
总结
本文围绕高并发场景下的数据库性能保障展开讨论,指出在海量数据与高并发访问的压力下,高性能数据库系统对业务支撑的重要性。并以 OceanBase 数据库为例,从 SQL 引擎、事务引擎、存储引擎、编译优化等多个角度解读了一款具备高性能的分布式数据库在高并发场景下的关键设计,基于上述设计与优化,OceanBase 得以支撑不同业务场景中的高并发、高性能诉求。希望本文能够为高并发系统的性能优化提供有价值的参考。
最后为大家推荐这个 OceanBase 开源负责人老纪的公众号「老纪的技术唠嗑局」,会持续更新和 #数据库、#AI、#技术架构 相关的各种技术内容。欢迎感兴趣的朋友们关注!
「老纪的技术唠嗑局」不仅希望能持续给大家带来有价值的技术分享,也希望能和大家一起为开源社区贡献一份力量。如果你对 OceanBase 开源社区认可,点亮一颗小星星✨吧!你的每一个 Star,都是我们努力的动力。
评论