OceanBase 数据库架构深度解析:从 Shared-Nothing 集群到多租户与日志流
【免费下载链接】oceanbaseOceanBase is the unified distributed database for the AI era — open-source, multi-model, one engine for your most demanding workloads.项目地址: https://gitcode.com/GitHub_Trending/oc/oceanbase
OceanBase 采用无共享(Shared-Nothing)的分布式集群架构,通过 Paxos 共识协议、分区与日志流机制实现高可用、水平扩展与多租户隔离。本文以官方架构文档为主体,结合本仓库源码实现,系统讲解 Zone、分区(Partition)、日志流(Log Stream)、OBServer、多租户、资源单元与 obproxy 等核心概念的底层原理与工程落地。
图中展示了 OceanBase 的分层架构:应用层通过多个 OBProxy 连接代理接入,OBProxy 将 SQL 请求路由到数据服务层的 OBServer 节点;OBServer 内部以分区(Partition)为单位组织数据,每个分区维护主副本(蓝色)与备副本(灰色),分布在多个 Zone(可用区)中,从而实现跨机房容灾与读写高可用。
一、Shared-Nothing 集群架构
OceanBase 的集群由若干完全对等的计算机节点组成,每个节点都拥有私有的物理资源(CPU、内存、硬盘等),并在其上运行独立的存储引擎、SQL 引擎与事务引擎。这就是无共享(Shared-Nothing)架构:节点之间相互独立,不共享内存或磁盘,仅通过网络设备相互协调,共同对外提供完整的数据库服务。
正是由于节点之间的独立性,OceanBase 获得了四大核心特性:
- 可扩展:新节点加入后,通过分区与日志流在节点间迁移即可完成水平扩容;
- 高可用:数据多副本分布在不同的节点/可用区,任一节点故障可由 Paxos 协议自动完成主副本切换;
- 高性能:读写请求由主副本就近处理,obproxy 将请求路由到数据所在节点,减少网络开销;
- 低成本:支持普通服务器集群部署,通过多租户共享资源摊薄硬件成本。
二、可用区(Zone)
集群中的节点分属于若干个可用区(Zone),每个节点属于且仅属于一个可用区。Zone 是一个逻辑概念,用于实现数据的高可用性和灾备特性。
- 可用区可以部署在不同的机房、不同区域甚至不同城市,从而支撑同城双活、两地三中心等不同层次的容灾场景;
- OceanBase 使用强一致性协议Paxos实现高可用,同一个 Paxos 组(即同一份数据的所有副本)位于不同的可用区;
- 一般建议至少部署 3 个 Zone,以保证在任意一个 Zone 故障时,多数派(Majority)副本仍然存活、集群可继续提供服务。
三、分区(Partition)与 Tablet
3.1 水平拆分的分区机制
在 OceanBase 中,一张表的数据可以按某种划分规则水平拆分为多个分片,每个分片称为一个表分区(Partition)。支持的分区类型包括:
- Hash 分区:按哈希值均匀分布,适合无自然区间可言的流水类数据;
- Range 分区:按值区间划分,适合按时间、ID 范围组织的业务数据;
- List 分区:按离散值枚举划分,适合按地区、类型等维度组织;
- 二级分区:例如交易库中的订单表,可以先按用户 ID 划分为若干一级分区,再按月份把每个一级分区细分为二级分区。
对于二级分区表,第二级的每个子分区才是物理分区,第一级分区只是逻辑概念。一个表的多个分区可以分布在一个可用区内的多个节点上,从而实现单表数据在多节点间的并行处理与负载均衡。
3.2 Tablet:分区的物理存储载体
每个物理分区都有一个用于存储数据的存储层对象,称为Tablet,用于存储有序的数据记录。从源码结构看,Tablet 是存储引擎(src/storage)侧的核心对象,承载 MemTable(内存表)与 SSTable(静态数据文件)之间的数据流转,是读写路径上的最小数据载体。
四、日志流(Log Stream)与 Paxos 复制
4.1 日志流的职责
当用户修改 Tablet 中的记录时,为了保证数据持久化,需要将重做日志(REDO)写入 Tablet 对应的日志流(Log Stream)。一个日志流对应其所在节点上的多个 Tablet,即同一节点上的多个 Tablet 可以共享一个日志流,由该日志流统一负责数据的持久化与复制。
4.2 主副本与从副本
Tablet 通过多副本机制保证高可用,副本一般分散在不同的可用区:
- 主副本(Leader):有且只有一个,接受修改操作,负责将日志复制给从副本;
- 从副本(Follower):其余副本,跟随主副本同步数据,不直接对外提供写服务。
主从副本之间通过基于Multi-Paxos的分布式共识协议保证数据一致性,而 Multi-Paxos 正是使用 Log Stream 来实现数据复制的。当多数派副本确认写入后,该日志即视为已提交(committed),这是 OceanBase 强一致性的核心来源。
4.3 源码印证:PALF 日志实现
日志流在仓库中由palf模块实现(目录 src/logservice/palf),模块内的关键实现包括:
- 日志块管理:
log_block_mgr.h/cpp、log_block_handler.h/cpp,负责日志文件的分配与回收; - 日志写入:
log_group_buffer.h/cpp、log_group_entry.h/cpp,负责日志的组提交与批量写入; - 日志读取:
log_iterator_impl.h、log_iterator_storage.h/cpp,用于日志回放与追平; - 日志补齐:
fetch_log_engine.h/cpp、log_learner.h/cpp,实现从副本向主副本拉取缺失日志; - 共识与选举:
election/algorithm/目录下包含election_impl、election_proposer、election_acceptor等实现,是 Paxos 选举与提案的核心算法。
在 log_define.h 中可以看到日志流的关键工程参数,帮助理解其设计取舍:
- 单条日志体最大 3.5MB(
MAX_LOG_BODY_SIZE = 3 * 1024 * 1024 + 512 * 1024); - 物理日志块大小为 64MB(
PALF_PHY_BLOCK_SIZE = 1 << 26); - Leader 的 group buffer 默认 32MB(
LEADER_DEFAULT_GROUP_BUFFER_SIZE = 1 << 25),Follower 在此基础上多预留 8MB; - 共识滑动窗口默认 2048(
PALF_SLIDING_WINDOW_SIZE = 1 << 11),Leader 最多并发提交的日志数为窗口的一半; - 日志同步延迟阈值 3 秒(
PALF_LOG_SYNC_DELAY_THRESHOLD_US = 3 * 1000 * 1000),可作为判断副本是否健康的标准。
4.4 日志流迁移与负载均衡
Tablet 可以在日志流之间迁移,以实现资源的负载均衡。这一能力与分区的分布调度相配合:当某节点负载过高时,可以通过迁移 Tablet 把数据与日志压力分散到其他节点,从而支持在线扩缩容与热点治理。
五、OBServer:单节点数据库服务
集群的每个节点上运行一个名为observer的服务进程(入口见 src/observer/main.cpp)。每个 observer 进程负责:
- 本节点上分区数据的存取;
- 路由到本机的 SQL 语句的解析与执行;
- 监听来自外部应用的连接请求,建立连接和数据库会话,对外提供数据库服务。
节点之间通过 TCP/IP 协议通信。observer 进程内部同时包含 SQL 引擎(src/sql)、存储引擎(src/storage)与事务引擎,是"计算与存储一体"的数据库服务节点。
六、多租户架构
6.1 租户即数据库实例
为简化大规模部署多个业务数据库的管理并降低资源成本,OceanBase 提供了多租户(Multi-Tenant)特性:在一个集群内可以创建多个相互隔离的数据库"实例",每个实例称为一个租户(Tenant)。从应用程序视角看,每个租户等同于一个独立的数据库实例。
- 每个租户可以选择MySQL 兼容模式或Oracle 兼容模式;
- 应用连接到 MySQL 租户后,可以创建用户、database,使用体验与独立 MySQL 库一致;
- 集群初始化后会自动存在一个名为
sys的系统租户,保存集群元数据,本身是 MySQL 兼容模式租户。
从源码结构看,多租户的核心实现在 src/observer/omt(OMT:Observer Multi-Tenant),其中 ob_multi_tenant.h 定义了ObMultiTenant类,提供create_tenant、create_tenant_without_unit、update_tenant_unit等接口,对应租户创建与资源单元变更等操作;租户对象的定义在 ob_tenant.h。
6.2 Meta 租户
除了系统租户与用户租户,OceanBase 还有一个特殊的Meta 租户:
- 每创建一个用户租户,系统就自动创建一个对应的 Meta 租户,生命周期与用户租户保持一致;
- Meta 租户用于存储和管理用户租户的集群私有数据,这部分数据不需要进行跨库物理同步以及物理备份恢复;
- 典型内容包含:配置项、位置信息、副本信息、日志流状态、备份恢复相关信息、合并信息等。
将集群私有的元数据与用户数据分离,是 OceanBase 多租户能够做到高效隔离与快速恢复的关键设计。
七、资源单元(Resource Unit)与资源池
为了隔离租户的资源,每个 observer 进程内可以有多个属于不同租户的虚拟容器,称为资源单元(resource unit)。资源单元封装了:
- CPU
- 内存
- 磁盘资源
多个资源单元组成一个资源池(resource pool),资源池用于指定:
- 使用哪个资源单元;
- 使用多少个资源单元;
- 资源分布的可用区。
创建租户时,指定所使用的资源池列表,即可控制租户可使用的资源总量与数据分布位置。这一机制配合ObMultiTenant::update_tenant_unit等接口(见 ob_multi_tenant.h),支持租户资源的在线调整。
八、obproxy:无状态连接代理
应用程序通常并不直接与 OBServer 建立连接,而是先连接obproxy,再由 obproxy 将 SQL 请求转发到合适的 OBServer 节点。
- 路由能力:obproxy 会缓存数据分区相关的信息,将 SQL 请求路由到尽量合适的 OBServer 节点,尽量做到"请求直达数据所在节点",减少跨节点转发开销;
- 无状态设计:obproxy 本身不保存任何持久化状态,多个 obproxy 节点可以通过网络负载均衡(SLB)对外提供统一的网络地址,实现代理层自身的水平扩展与高可用;
- 兼容接入:在 SQL 引擎侧也存在与 obproxy 的交互逻辑(例如 src/sql/optimizer/ob_route_policy.h 中的路由策略定义),进一步印证了"路由到合适节点"这一设计在查询优化层面的配合。
九、架构总结
回顾全文,OceanBase 的架构可以概括为一条完整的数据链路:
- 接入层:应用 → SLB → 多个无状态 obproxy,统一入口并做初步路由;
- 服务层:obproxy 将请求转发至 Zone 内合适的 observer 进程,observer 负责 SQL 解析执行与数据存取;
- 数据层:数据按分区(Partition)水平拆分,每个分区对应一个 Tablet 存储载体,Tablet 归属于日志流(Log Stream);
- 一致性层:日志流基于 Multi-Paxos 在多个 Zone 的副本间复制 REDO 日志,主副本(Leader)对外服务,多数派确认即提交;
- 隔离层:资源单元/资源池划分 CPU、内存与磁盘,多租户(含系统租户、用户租户与 Meta 租户)在同一集群内实现相互隔离的数据库实例。
这套"Shared-Nothing + Paxos + 分区/日志流 + 多租户"的组合,构成了 OceanBase 可扩展、高可用、高性能、低成本四大特性的底层根基,也是理解其后续存储、事务与 SQL 引擎实现的总纲。
【免费下载链接】oceanbaseOceanBase is the unified distributed database for the AI era — open-source, multi-model, one engine for your most demanding workloads.项目地址: https://gitcode.com/GitHub_Trending/oc/oceanbase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考