BlueStore对象存储与元数据管理分析
1. 概述
BlueStore是Ceph的默认对象存储后端,采用了一种创新的存储架构:
- 数据直接存储在块设备上:避免传统文件系统的开销
- 元数据存储在RocksDB中:提供高性能的元数据管理
- 分离式设计:数据路径和元数据路径完全分离
2. 对象存储架构
2.1 存储层次结构
BlueStore采用多层次的存储抽象,从逻辑对象到物理存储的映射关系如下:
1 | Object (Onode) |
2.1.1 Onode (Object Node)
定义位置: BlueStore.h:1328
Onode是对象的内存表示,包含:
- 对象标识符 (
ghobject_t oid): 唯一标识一个对象 - 对象元数据 (
bluestore_onode_t onode): 存储在RocksDB中的元数据 - ExtentMap (
extent_map): 逻辑extent到Blob的映射 - BufferSpace (
bc): 缓存的数据缓冲区
1 | struct Onode { |
元数据存储:
- Onode的元数据存储在RocksDB中,键为
PREFIX_OBJ + key - 包含对象大小、修改时间、扩展属性等信息
2.1.2 Extent (逻辑Extent)
定义位置: BlueStore.h:829
Extent将对象的逻辑偏移映射到Blob:
1 | struct Extent { |
特点:
- Extent按
logical_offset排序,存储在boost::intrusive::set中 - 一个对象可以有多个Extent,支持稀疏对象
- Extent可以跨越多个Blob(通过spanning blob机制)
2.1.3 Blob (数据块)
定义位置: BlueStore.h:651 和 bluestore_types.h:498
Blob是数据的逻辑容器,包含:
1 | struct Blob { |
Blob元数据 (bluestore_blob_t):
1 | struct bluestore_blob_t { |
Blob特性:
- 压缩支持: 可以存储压缩数据,通过
FLAG_COMPRESSED标志 - 校验和: 支持数据完整性校验,通过
FLAG_CSUM标志 - 共享Blob: 多个对象可以共享同一个Blob(写时复制)
- 引用计数: 通过
bluestore_blob_use_tracker_t跟踪使用情况
2.1.4 PExtent (物理Extent)
定义位置: bluestore_types.h:98
PExtent表示块设备上的实际物理位置:
1 | struct bluestore_pextent_t { |
特点:
- 一个Blob可以包含多个PExtent(支持不连续存储)
- PExtent由Allocator分配和管理
- 支持对齐到块大小边界
2.2 数据写入流程
2.2.1 写入路径
接收写入请求
- 客户端请求写入对象数据
- BlueStore创建或获取Onode
分配空间
- 通过Allocator分配物理空间(PExtent)
- 创建或扩展Blob来容纳数据
数据准备
- 可选:压缩数据(如果启用)
- 可选:计算校验和
- 准备写入缓冲区
写入块设备
- 直接写入到块设备(绕过文件系统)
- 使用异步I/O提高性能
更新元数据
- 创建或更新Extent映射
- 更新Blob元数据
- 更新Onode元数据
提交事务
- 将元数据变更写入RocksDB事务
- 提交事务,确保一致性
2.2.2 关键代码路径
写入入口: BlueStore::_do_write()
- 创建
WriteContext管理写入操作 - 调用
Writer::do_write()执行实际写入
Writer类: Writer.h 和 Writer.cc
- 管理写入的数据块(blob_data_t)
- 处理压缩、对齐等操作
- 协调空间分配和数据写入
2.3 数据读取流程
查找Onode
- 从RocksDB读取对象元数据
- 加载到内存缓存
解析ExtentMap
- 根据逻辑偏移查找对应的Extent
- 确定需要读取的Blob和偏移
读取数据
- 从块设备读取物理数据
- 可选:验证校验和
- 可选:解压缩数据
返回数据
- 将数据返回给客户端
- 可能缓存到BufferSpace中
3. 元数据管理
3.1 元数据存储架构
BlueStore使用RocksDB作为元数据存储引擎:
1 | KeyValueDB *db = nullptr; // RocksDB实例 |
3.1.1 元数据类型
1. 对象元数据 (Onode)
- 键格式:
PREFIX_OBJ + key - 值内容: 序列化的
bluestore_onode_t - 包含信息:
- 对象大小
- 修改时间
- 扩展属性
- ExtentMap的编码(如果较小则内联)
2. Blob元数据
- 存储位置: 内联在Onode中(小对象)或单独存储(大对象)
- SharedBlob: 共享Blob的元数据单独存储
- 键格式:
PREFIX_SHARED_BLOB + sbid - 包含引用计数、物理extent等信息
- 键格式:
3. 集合元数据 (Collection)
- 键格式:
PREFIX_COLL + cid - 值内容: 集合的元数据(如bits等)
4. OMap数据
- 键格式:
omap_prefix + onode_key + user_key - 值内容: 用户定义的键值对
3.2 元数据组织
3.2.1 ExtentMap编码
ExtentMap可以以两种方式存储:
1. 内联存储 (小对象)
- ExtentMap直接编码在Onode中
- 适合extent数量少的对象
2. 分片存储 (大对象)
- ExtentMap分成多个shard
- 每个shard独立编码和存储
- 支持按需加载,减少内存占用
编码格式:
1 | // Extent编码包含: |
3.2.2 SharedBlob管理
目的: 支持写时复制(Copy-on-Write),多个对象可以共享数据
结构:
1 | struct SharedBlob { |
引用计数:
- 使用
bluestore_extent_ref_map_t跟踪每个extent的引用数 - 当引用计数为0时,可以释放物理空间
3.3 事务管理
3.3.1 TransContext
定义位置: BlueStore.h:276
每个事务由TransContext管理:
1 | struct TransContext { |
3.3.2 事务流程
开始事务
- 创建
TransContext - 创建RocksDB事务
- 创建
记录变更
- 修改Onode元数据
- 更新ExtentMap
- 记录Blob变更
提交事务
- 将元数据变更写入RocksDB
- 确保原子性
同步
- 可选:同步RocksDB(fsync)
- 确保数据持久化
3.4 缓存管理
3.4.1 Onode缓存
结构: OnodeCacheShard
- 缓存Onode对象
- 使用LRU策略管理
- 支持分片(sharding)提高并发性
3.4.2 Buffer缓存
结构: BufferCacheShard
- 缓存对象数据缓冲区
- 管理
Buffer对象的状态(EMPTY/CLEAN/WRITING) - 支持延迟写入(deferred write)
3.4.3 缓存策略
- LRU: 最近最少使用
- TwoQ: 两级队列(热数据和冷数据)
- 优先级缓存: 根据访问模式调整优先级
4. 空间管理
4.1 Allocator (分配器)
BlueStore使用Allocator管理块设备上的空闲空间:
支持的分配器类型:
- StupidAllocator: 简单的interval_set实现
- BitmapAllocator: 基于位图的分配器
- AvlAllocator: 基于AVL树的分配器
- BtreeAllocator: 基于B树的分配器
- Btree2Allocator: B树分配器的改进版
- HybridAllocator: 混合分配器(主分配器+位图分配器)
分配流程:
- 根据请求大小和提示(hint)选择分配策略
- 从空闲空间中找到合适的extent
- 返回分配的PExtent列表
4.2 FreelistManager (空闲列表管理器)
作用: 持久化空闲空间信息到RocksDB
实现: BitmapFreelistManager
- 使用位图跟踪空闲块
- 支持合并操作符(XOR)进行增量更新
- 在RocksDB中持久化空闲空间状态
5. 高级特性
5.1 压缩
支持: 通过Compression.h和Compression.cc实现
压缩流程:
- Estimator: 估算压缩收益
- Scanner: 扫描可压缩的数据
- 压缩执行: 使用配置的压缩算法
- 元数据更新: 更新Blob的压缩标志和长度
压缩标志: bluestore_blob_t::FLAG_COMPRESSED
5.2 校验和
支持: 通过Checksummer实现
校验和类型:
- CRC32C
- XXHASH32
- XXHASH64
存储: 校验和数据存储在bluestore_blob_t::csum_data中
5.3 共享Blob (写时复制)
场景:
- 对象克隆
- 快照
- 去重
机制:
- 多个对象共享同一个Blob
- 写入时创建新的Blob(写时复制)
- 通过引用计数管理生命周期
6. 性能优化
6.1 延迟写入 (Deferred Write)
目的: 合并小写入,提高性能
机制:
- 小写入先缓存到
DeferredBatch - 延迟到合适时机批量写入
- 减少I/O次数
6.2 对齐优化
块对齐:
- 数据对齐到块大小边界
- 提高I/O效率
分配对齐:
- 根据分配单元对齐
- 减少碎片
6.3 缓存优化
多级缓存:
- Onode缓存(元数据)
- Buffer缓存(数据)
- 块设备缓存(操作系统级)
缓存策略:
- 根据访问模式调整
- 支持预热和预取
7. 数据一致性
7.1 事务保证
- 原子性: 通过RocksDB事务保证
- 持久性: 通过fsync保证
- 一致性: 通过写前日志(WAL)保证
7.2 崩溃恢复
- RocksDB恢复: 自动恢复未提交的事务
- 空间一致性: 通过FreelistManager重建空闲空间
- 元数据校验: 启动时验证元数据完整性
8. 总结
BlueStore的存储架构具有以下特点:
- 分离式设计: 数据和元数据分离存储,各自优化
- 直接I/O: 数据直接写入块设备,避免文件系统开销
- 灵活映射: 多层次的映射关系,支持稀疏对象和共享数据
- 高性能: 通过缓存、延迟写入、对齐等优化提高性能
- 可扩展: 支持压缩、校验和、共享Blob等高级特性
这种设计使得BlueStore能够提供高性能、高可靠性的对象存储服务,特别适合大规模分布式存储场景。
9. 关键数据结构关系图
1 | ┌─────────────────┐ |
10. 参考代码位置
- 核心类定义:
cephMain/src/os/bluestore/BlueStore.h - 核心实现:
cephMain/src/os/bluestore/BlueStore.cc - 类型定义:
cephMain/src/os/bluestore/bluestore_types.h - 写入器:
cephMain/src/os/bluestore/Writer.h/cc - 压缩:
cephMain/src/os/bluestore/Compression.h/cc - 分配器:
cephMain/src/os/bluestore/Allocator*.h/cc - 空闲列表:
cephMain/src/os/bluestore/FreelistManager.h/cc
正在加载留言…