PostgreSQL码农集散地

OceanBase 源码学习: 3.2 Tablet 管理系统

OceanBase 源码学习: 3.2 Tablet 管理系统

本文介绍 OceanBase 中的 Tablet 管理系统,该系统负责处理数据分片(称为 Tablet)的生命周期、持久化和内存管理。Tablet 是基础存储单元,包含用于写入的活跃内存表 (memtable) 和用于存储历史数据的持久化表 SSTable。

概述

Tablet 管理系统负责:

  • Tablet 生命周期:创建、更新和删除数据分片(Tablet)
  • 内存管理:有效管理在内存中的 tablet 元数据和对象
  • 持久性:负责 tablet 在 写入/读取 持久化存储过程中的序列化和反序列化
  • 表存储管理:组织每个 Tablet 中的 SSTable 和 memtable
  • 访问控制:通过 pointer handles 提供对 tablet 的线程安全访问

该系统在日志流 (LS/Log Streams) 环境中运行,其中每个 LS 包含代表不同数据分片的多个 tablet。

核心架构

Tablet 管理系统由几个协同工作的关键组件组成:



Image

源文件:

  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/ls/ob_ls_tablet_service.h#L103-L106
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.h#L154-L177
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h#L126-L189
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_persister.h#L272-L281

Tablet 生命周期管理

Tablet 会经历几个生命周期状态,这些状态由 ObLSTabletService 管理:



Image

Tablet 的创建

Tablet 通过多种路径生成:

1、首次创建:   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L294-L401

  • init_for_first_time_creation() 负责初始化一个全新的 Tablet
  • 如果有必要,创建空的 major SSTable
  • 设置初始元数据和 schema

2、迁移时创建:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/ls/ob_ls_tablet_service.cpp#L761-L818

  • migrate_create_tablet() 负责在数据迁移期间创建 Tablet
  • 使用 ObMigrationTabletParam 重建 Tablet 状态

3、转移时创建:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/ls/ob_ls_tablet_service.cpp#L1832-L1869

  • create_transfer_in_tablet() 负责在 LS 之间转移 Tablet

Tablet 的更新

Tablet 会在压缩和合并操作期间进行更新:

合并更新:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L416-L550

  • init_for_merge() 在压缩(compaction)数据后创建新的 tablet 版本
  • 使用新的 SSTables 更新表存储
  • 保存 Tablet 元数据并调整版本

Tablet 的删除

Tablet 的移除通过两阶段过程进行:

1、逻辑删除:代码见:   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/ls/ob_ls_tablet_service.cpp#L336-L383

  • remove_tablet() 从活跃服务中移除 Tablet
  • 移至垃圾收集队列

2、物理删除:代码见:   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp#L527-L547

  • inner_remove_tablet() 从内存管理中删除 Tablet
  • 释放所有相关资源

源文件:

  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/ls/ob_ls_tablet_service.cpp#L155-L383
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L294-L550
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp#L501-L547

内存管理架构

Tablet 内存管理系统采用带有对象池(object pools)和引用计数器(reference counting)的分层方法:



Image

对象池管理

系统为不同尺寸的 tablet 维护单独的池:

普通池(Normal Pool, 3,824 bytes per tablet):  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h#L130-L130

大池(Large Pool, 65,480 bytes per tablet): https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h#L131-L131

池的选择逻辑:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp#L199-L219

int ObTenantMetaMemMgr::choose_tablet_pool_type(  
    const bool is_user_tablet,  
    const int64_t must_cache_size,  
    const int64_t try_cache_size,  
    ObTabletPoolType &type)  

引用计数

Tablet 使用原子引用计数来确保内存安全:

  • inc_ref() 和 dec_ref() 代码见:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.h#L183-L185
  • 当引用计数降到零时自动清理 ( 类似PostgreSQL LRU中的sweep clock? )
  • 通过 ObTabletHandle 与 RAII 包装器(wrapper)集成

垃圾回收

该系统包括自动垃圾收集:

  • Tablet GC 定期清理任务:代码见:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp#L72-L80
  • 内存压力:清洗功能在内存压力期间自动触发
  • 基于队列的处理, FIFO Tablet 清理模式:代码见:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp#L105-L156

源文件:

  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.h#L126-L182
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tenant_meta_mem_mgr.cpp#L158-L428
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/meta_mem/ob_tablet_pointer.cpp#L118-L147

表存储组织

每个 tablet 都包含一个 ObTabletTableStore 组织其数据表:



Image

表存储组件

表存储管理几种类型的表:

1、Major SSTables:   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.h#L173-L174

  • Long-term historical data
  • Result of major compaction

2、Minor SSTables:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.h#L175-L176

  • Incremental changes between major compactions
  • Result of minor compaction

3、DDL SSTables:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.h#L177-L178

  • Schema change operations
  • Direct load operations

4、Memtables:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.h#L181-L182

  • Active write buffer in memory
  • Converted to minor SSTables during freeze

扩展阅读:

表存储更新

表存储更新发生在压缩操作期间, 如:

  • 创建新的表存储  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.cpp#L226-L242
  • 替换 SSTable  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.cpp#L1105-L1150
  • 管理内存表  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.cpp#L1644-L1675

源文件:

  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.h#L78-L193
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_table_store.cpp#L78-L243
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_table_store_util.h#L36-L182

Tablet 持久化

持久化系统负责将 tablet 序列化到磁盘、将磁盘中的 tablet 反序列化并加载回内存:



Image

持久化操作

ObTabletPersister 处理核心持久化操作:

1、Tablet 转换:代码见:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_persister.cpp#L326-L342

  • persist_and_transform_tablet() 将内存表示转换为磁盘格式
  • 处理不同的持久化上下文(private, shared, etc.)

2、序列化:代码见:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L353-L395

  • serialize() 将 Tablet 数据写入缓冲区(buffer)
  • 包括所有组件地址和元数据

3、反序列化:代码见:  https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L360-L393

  • load_deserialize() 用磁盘中存储的数据重建 Tablet
  • deserialize_post_work() 完成加载过程

地址管理

Tablet 对其组件使用复杂的寻址:

  • Tablet 地址:指向 major Tablet 数据   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_complex_addr.h
  • 表存储 地址:表存储数据的引用
  • 存储 schema 地址:对 schema 信息的引用
  • 宏信息 地址:引用宏块信息地址

持久化上下文

支持不同的持久化上下文:

  • 私有存储:标准的本地存储持久性
  • 共享存储:具有不同寻址的共享存储模式   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_persister.cpp#L306-L324
  • 传输操作:Tablet 迁移期间的特殊处理

源文件:

  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_persister.h#L272-L294
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet_persister.cpp#L272-L342
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L353-L395

集成点

Tablet 管理系统与 OceanBase 的其他几个组件集成:

事务系统集成

  • 事务上下文:Tablet 参与分布式事务
  • MVCC 支持:表存储为 MVCC 读取维护多个版本
  • 锁管理:与锁内存表集成,实现行级锁

schema 管理集成

  • 存储 schema:每个 Tablet 都维护其存储 schema   https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.h#L575-L575
  • schema 版本:Tablet跟踪模式随时间的变化
  • DDL 操作:针对 schema 更改操作的特殊处理

压缩集成

  • Medium 信息:Tablets 压缩调度信息
  • 合并操作:major/minor tablet 压缩(compaction)期间的表存储更新
  • compaction 历史:跟踪已完成的 compaction 操作

高可用性集成

  • 迁移支持:迁移期间的 Tablet 创建和更新
  • 备份/恢复:Tablet 持久化存储支持备份操作
  • 传输操作:在日志流(LS)之间移动 Tablet

源文件:

  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/ls/ob_ls_tablet_service.h#L340-L457
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.h#L554-L627
  • https://github.com/oceanbase/oceanbase/blob/8e2580cf/src/storage/tablet/ob_tablet.cpp#L416-L550

更多详细内容请关注我的github: https://github.com/digoal/blog