BlueStore软件架构流程分析
目录
- BlueStore概述
- 整体架构
- 核心组件
- 数据模型
- 写入流程
- 读取流程
- 事务处理
- 空间管理
- 缓存机制
- 压缩和校验
BlueStore概述
1.1 什么是BlueStore
BlueStore 是Ceph的默认对象存储后端,直接在块设备上存储对象数据,避免了传统文件系统的开销。它是为高性能SSD设计的存储后端。
1.2 核心特点
- 直接管理块设备:绕过文件系统,直接在块设备上操作
- 元数据存储在RocksDB:使用RocksDB存储所有元数据
- BlueFS文件系统:轻量级文件系统,用于存储RocksDB的WAL和SST文件
- 写时分配(COW):支持克隆和快照
- 内联压缩:支持数据压缩
- 校验和:支持数据完整性校验
- 多设备支持:支持WAL、DB、慢速设备分离
1.3 与传统文件系统的区别
| 特性 |
传统文件系统(FileStore) |
BlueStore |
| 数据存储 |
通过文件系统 |
直接在块设备 |
| 元数据 |
文件系统元数据 |
RocksDB |
| 性能 |
受文件系统限制 |
更高性能 |
| 开销 |
双重写入(数据+元数据) |
单次写入 |
| 适用场景 |
通用场景 |
SSD优化 |
整体架构
2.1 架构层次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ┌─────────────────────────────────────────────────────────┐ │ ObjectStore接口 │ │ (OSD层调用的存储接口) │ └───────────────────────┬───────────────────────────────────┘ │ ┌───────────────────────▼───────────────────────────────────┐ │ BlueStore核心 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Collection │ │ Onode │ │ Buffer │ │ │ │ (集合) │ │ (对象节点) │ │ (缓冲区) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Extent │ │ Blob │ │ SharedBlob │ │ │ │ (逻辑范围) │ │ (数据块) │ │ (共享块) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ └───────────────────────┬───────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ┌───────▼──────┐ ┌─────▼──────┐ ┌─────▼──────┐ │ Allocator │ │ Freelist │ │ BlueFS │ │ (分配器) │ │ Manager │ │ (文件系统) │ │ │ │ (空闲管理) │ │ │ └───────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ │ │ ┌───────▼───────────────▼───────────────▼──────┐ │ RocksDB (元数据) │ │ (通过BlueFS存储WAL和SST) │ └───────────────────────┬───────────────────────┘ │ ┌───────────────────────▼───────────────────────┐ │ 块设备 (BlockDevice) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ WAL │ │ DB │ │ Slow │ │ │ │ (快速) │ │ (快速) │ │ (慢速) │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └───────────────────────────────────────────────┘
|
2.2 设备布局
BlueStore支持三种设备类型:
WAL设备:存储RocksDB的WAL(Write-Ahead Log)文件
DB设备:存储RocksDB的SST文件
慢速设备(Slow):存储对象数据
设备布局示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 块设备布局: ┌─────────────────────────────────────────┐ │ Label (设备标签) │ │ - OSD UUID │ │ - 设备大小 │ │ - 创建时间 │ └─────────────────────────────────────────┘ ┌─────────────────────────────────────────┐ │ BlueFS (如果使用BlueFS) │ │ - WAL文件 │ │ - SST文件 │ └─────────────────────────────────────────┘ ┌─────────────────────────────────────────┐ │ BlueStore数据区 │ │ - 对象数据 │ │ - 空闲空间由Allocator管理 │ └─────────────────────────────────────────┘
|
核心组件
3.1 BlueStore类
位置:BlueStore.h / BlueStore.cc
职责:
- 实现ObjectStore接口
- 管理所有存储操作(read、write、transaction等)
- 协调各个子组件
关键成员:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class BlueStore : public ObjectStore { BlockDevice *bdev; BlockDevice *bdev_slow; BlockDevice *bdev_wal; BlockDevice *bdev_db; KeyValueDB *db; BlueFS *bluefs; Allocator *alloc; FreelistManager *fm; OnodeCache *onode_cache; BufferCache *buffer_cache; ceph::unordered_map<coll_t, CollectionRef> coll_map; };
|
3.2 Collection(集合)
位置:BlueStore.h 内部结构
职责:
- 管理一个PG(Placement Group)的对象集合
- 维护Onode缓存
- 管理事务上下文
关键成员:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| struct Collection { coll_t cid; bluestore_cnode_t cnode; OnodeCacheShard *onode_cache; ceph::unordered_map<ghobject_t, OnodeRef> onode_map; SharedBlobSet shared_blob_set; PerfCounters *logger; };
|
3.3 Onode(对象节点)
位置:BlueStore.h 内部结构
职责:
- 表示一个对象的元数据
- 管理对象的逻辑到物理映射(ExtentMap)
- 管理对象的缓冲区(BufferSpace)
关键成员:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| struct Onode { ghobject_t oid; bluestore_onode_t onode; ExtentMap extent_map; BufferSpace buffer_space; OMapSpace omap_space; std::atomic_int nref; };
|
Onode元数据结构(bluestore_onode_t):
1 2 3 4 5 6 7 8 9
| struct bluestore_onode_t { uint64_t nid; uint64_t size; utime_t mtime; utime_t atime; uint32_t expected_object_size; uint32_t alloc_hint_flags; };
|
3.4 Extent(逻辑范围)
位置:BlueStore.h 内部结构
职责:
关键成员:
1 2 3 4 5 6
| struct Extent { uint32_t logical_offset; uint32_t length; BlobRef blob; uint32_t blob_offset; };
|
3.5 Blob(数据块)
位置:BlueStore.h 内部结构
职责:
- 表示物理存储的数据块
- 管理物理extent(pextent)
- 支持压缩和校验
关键成员:
1 2 3 4 5 6 7 8 9 10
| struct Blob { uint64_t id; bluestore_blob_t blob; PExtentVector extents; SharedBlobRef shared_blob; };
|
Blob元数据结构(bluestore_blob_t):
1 2 3 4 5 6 7 8 9 10 11
| struct bluestore_blob_t { uint64_t id; uint32_t logical_length; uint32_t compressed_length; uint8_t compression; uint8_t csum_type; uint8_t csum_chunk_order; uint32_t flags; PExtentVector extents; bluestore_extent_ref_map_t ref_map; };
|
3.6 SharedBlob(共享Blob)
位置:BlueStore.h 内部结构
职责:
- 管理共享Blob的引用计数
- 支持写时复制(COW)
- 管理共享Blob的缓冲区缓存
关键成员:
1 2 3 4 5 6 7
| struct SharedBlob { std::atomic_int nref; bluestore_shared_blob_t *persistent; bluestore_extent_ref_map_t ref_map; };
|
3.7 Buffer(缓冲区)
位置:BlueStore.h 内部结构
职责:
状态:
STATE_CLEAN:干净状态(已写入磁盘)
STATE_WRITING:正在写入
STATE_DIRTY:脏数据(待写入)
3.8 BlueFS(文件系统)
位置:BlueFS.h / BlueFS.cc
职责:
- 轻量级文件系统
- 管理RocksDB的WAL和SST文件
- 直接在块设备上操作
关键特性:
- 日志结构文件系统
- 支持三种设备(WAL、DB、Slow)
- 文件分配和回收
3.9 Allocator(分配器)
位置:Allocator.h / 各种实现
职责:
- 管理空闲空间
- 分配物理extent
- 支持多种分配算法
分配器类型:
- StupidAllocator:简单分配器
- BitmapAllocator:位图分配器
- AvlAllocator:AVL树分配器
- BtreeAllocator:B树分配器
- Btree2Allocator:B树2分配器
- HybridAllocator:混合分配器
3.10 FreelistManager(空闲列表管理器)
位置:FreelistManager.h / 实现
职责:
- 持久化空闲空间信息到RocksDB
- 管理空闲空间的分配和释放
- 支持多种实现(Bitmap、Btree等)
数据模型
4.1 逻辑到物理映射
1 2 3 4 5 6 7 8 9 10 11 12 13
| 对象 (Object) │ ├─► Onode (对象元数据) │ │ │ └─► ExtentMap (逻辑范围映射) │ │ │ ├─► Extent 1: [0, 1MB) → Blob A │ ├─► Extent 2: [1MB, 2MB) → Blob B │ └─► Extent 3: [2MB, 3MB) → Blob A (共享) │ └─► BufferSpace (缓冲区空间) │ └─► Buffer缓存 (内存中的数据)
|
4.2 物理存储结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Blob (数据块) │ ├─► 物理Extent列表 │ ├─► PExtent 1: [offset=100MB, length=1MB] │ ├─► PExtent 2: [offset=200MB, length=1MB] │ └─► PExtent 3: [offset=500MB, length=1MB] │ ├─► 压缩信息 │ ├─► 压缩算法: snappy │ ├─► 原始长度: 2MB │ └─► 压缩长度: 1.5MB │ └─► 校验和信息 ├─► 校验和类型: crc32c └─► 校验和块: 每64KB一个校验和
|
4.3 RocksDB键空间
BlueStore使用以下键前缀:
1 2 3 4 5 6 7 8
| PREFIX_SUPER = "S" // 超级块信息 PREFIX_STAT = "T" // 统计信息 PREFIX_COLL = "C" // Collection元数据 PREFIX_OBJ = "O" // Onode元数据 PREFIX_OMAP = "M" // OMAP键值对 PREFIX_DEFERRED = "L" // 延迟事务 PREFIX_ALLOC = "B" // 空闲空间(FreelistManager) PREFIX_SHARED_BLOB = "X" // 共享Blob元数据
|
4.4 对象键编码
对象键的编码格式:
1 2 3
| [shard_id + 0x80] + [pool_id + 2^63] + [hash(bit_reversed)] + [namespace(escaped)] + [key(escaped)] + ['<'|'='|'>'] + [object_name(escaped)] + [snap] + [generation] + ['o']
|
写入流程
5.1 写入流程概览
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 客户端写入请求 │ ▼ BlueStore::write() │ ├─► 获取或创建Collection ├─► 获取或创建Onode └─► 创建事务上下文 (TransContext) │ ▼ Writer::do_write() │ ├─► 处理缓冲区 (BufferSpace) ├─► 分配空间 (Allocator) ├─► 创建Blob ├─► 压缩数据 (可选) ├─► 计算校验和 └─► 调度I/O │ ▼ BlueStore::_txc_add_transaction() │ ├─► 准备事务 (prepare) ├─► 提交I/O (aio_submit) ├─► 等待I/O完成 (aio_wait) └─► 提交元数据 (kv_commit) │ ▼ 事务完成
|
5.2 详细写入步骤
步骤1:接收写入请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| int BlueStore::write( coll_t cid, const ghobject_t& oid, uint64_t offset, size_t len, const bufferlist& bl, uint32_t fadvise_flags) { CollectionRef c = _get_collection(cid); OnodeRef o = c->get_onode(oid, true); TransContext *txc = _get_trans_context(c); Writer w(this, txc, wctx, o); w.do_write(offset, bl); _txc_add_transaction(txc); return 0; }
|
步骤2:Writer处理写入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void Writer::do_write(uint32_t location, bufferlist& data) { blob_vec blobs; _split_data(location, data, blobs); _align_to_disk_block(location, ref_end, blobs); _do_put_blobs(location, data_end, ref_end, blobs, after_punch_it); _defer_or_allocate(need_size); _do_put_new_blobs(location, ref_end, bd_it, bd_end); }
|
步骤3:空间分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void Writer::_defer_or_allocate(uint32_t need_size) { if (should_defer) { do_deferred = true; return; } PExtentVector extents; int64_t allocated = alloc->allocate( need_size, block_size, max_alloc_size, hint, &extents); allocated.insert(allocated.end(), extents.begin(), extents.end()); }
|
步骤4:Blob创建和数据放置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| BlobRef Writer::_blob_create_with_data( uint32_t in_blob_offset, bufferlist& disk_data) { BlobRef b = new Blob(); b->id = generate_blob_id(); PExtentVector extents; _get_disk_space(disk_data.length(), extents); b->extents = extents; b->blob.logical_length = disk_data.length(); b->blob.compressed_length = compressed ? compressed_size : 0; b->blob.compression = compression_algorithm; if (csum_type) { calculate_checksums(b, disk_data); } return b; }
|
步骤5:调度I/O
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void Writer::_schedule_io( const PExtentVector& disk_extents, bufferlist data) { for (auto& e : disk_extents) { uint64_t disk_offset = e.offset; uint32_t length = e.length; IOContext *ioc = new IOContext(); ioc->aio_write(disk_offset, data); txc->aio_write_queue.push_back(ioc); } }
|
步骤6:事务提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void BlueStore::_txc_add_transaction(TransContext *txc) { _txc_prepare(txc); ├─► 更新Onode元数据 ├─► 更新ExtentMap ├─► 更新Blob元数据 └─► 准备RocksDB事务 _txc_submit_aio(txc); └─► 提交所有AIO请求到块设备 _txc_aio_wait(txc); └─► 等待所有AIO完成 _txc_commit_kv(txc); └─► 提交RocksDB事务 _txc_finish(txc); ├─► 更新缓存 ├─► 释放资源 └─► 更新统计信息 }
|
5.3 小写优化
对于小写(小于bluestore_small_io_size),BlueStore使用特殊优化:
- 内联写入:小数据直接写入Onode的OMAP
- 延迟分配:先写入缓冲区,稍后批量分配空间
- 合并写入:多个小写合并为一个大写
5.4 大写处理
对于大写(大于bluestore_big_io_size),BlueStore:
- 直接分配:立即分配空间
- 直接写入:直接写入块设备,不经过缓冲区
- 支持压缩:如果启用压缩,会压缩数据
读取流程
6.1 读取流程概览
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 客户端读取请求 │ ▼ BlueStore::read() │ ├─► 获取Collection ├─► 获取Onode └─► 从BufferSpace读取 │ ├─► 检查缓冲区缓存 │ ├─► 命中:直接返回 │ └─► 未命中:继续 │ ├─► 查找ExtentMap │ └─► 确定需要读取的Blob │ ├─► 从Blob读取数据 │ ├─► 查找物理extent │ ├─► 调度AIO读取 │ ├─► 等待I/O完成 │ ├─► 验证校验和 │ └─► 解压缩(如果需要) │ └─► 更新缓存 └─► 将数据加入BufferSpace
|
6.2 详细读取步骤
步骤1:接收读取请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| int BlueStore::read( coll_t cid, const ghobject_t& oid, uint64_t offset, size_t len, bufferlist& bl, uint32_t op_flags) { CollectionRef c = _get_collection(cid); OnodeRef o = c->get_onode(oid, false); if (!o) { return -ENOENT; } ready_regions_t ready; interval_set<uint32_t> missing; o->buffer_space.read( cache, offset, len, ready, missing); if (!missing.empty()) { _read_from_disk(o, missing, bl); } return 0; }
|
步骤2:从BufferSpace读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void BufferSpace::read( BufferCacheShard* cache, uint32_t offset, uint32_t length, ready_regions_t& res, interval_set<uint32_t>& res_intervals) { auto it = _data_lower_bound(offset); uint32_t pos = offset; uint32_t end = offset + length; while (pos < end && it != buffer_map.end()) { Buffer& b = *it; if (b.offset <= pos && pos < b.offset + b.length) { uint32_t b_off = pos - b.offset; uint32_t b_len = min(b.length - b_off, end - pos); res[pos] = b.data.substr(b_off, b_len); res_intervals.insert(pos, b_len); pos += b_len; } else if (pos < b.offset) { res_intervals.insert(pos, b.offset - pos); pos = b.offset; } else { ++it; } } if (pos < end) { res_intervals.insert(pos, end - pos); } }
|
步骤3:从磁盘读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void BlueStore::_read_from_disk( OnodeRef o, interval_set<uint32_t>& missing, bufferlist& bl) { for (auto& p : missing) { uint32_t offset = p.first; uint32_t length = p.second; auto extents = o->extent_map.get_containing_extents(offset, length); for (auto& ext : extents) { BlobRef blob = ext.blob; uint32_t blob_offset = ext.blob_offset + (offset - ext.logical_offset); _read_blob(blob, blob_offset, length, bl); } } }
|
步骤4:从Blob读取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| void BlueStore::_read_blob( BlobRef blob, uint32_t blob_offset, uint32_t length, bufferlist& bl) { PExtentVector extents = blob->get_extents_containing(blob_offset, length); vector<IOContext*> ios; for (auto& e : extents) { uint64_t disk_offset = e.offset + (blob_offset - e.logical_offset); IOContext *ioc = new IOContext(); ioc->aio_read(disk_offset, length); ios.push_back(ioc); } bdev->aio_submit(ios); for (auto ioc : ios) { ioc->wait(); if (blob->blob.csum_type) { verify_checksum(blob, ioc->bl); } if (blob->blob.compression) { decompress(blob, ioc->bl); } bl.append(ioc->bl); } o->buffer_space.did_read(cache, blob_offset, std::move(bl)); }
|
6.3 读取优化
- 预读(Read-ahead):预测性读取相邻数据
- 缓存命中:优先从BufferSpace读取
- 并行读取:多个extent并行读取
- 校验和验证:读取时验证数据完整性
事务处理
7.1 事务模型
BlueStore使用两阶段提交:
准备阶段(Prepare):
- 更新内存中的元数据
- 准备RocksDB事务
- 调度AIO操作
提交阶段(Commit):
- 等待AIO完成
- 提交RocksDB事务
- 更新缓存状态
7.2 TransContext(事务上下文)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| struct TransContext { CollectionRef collection; ObjectStore::Transaction t; list<IOContext*> aio_write_queue; list<IOContext*> aio_read_queue; uint64_t bytes_written; uint64_t bytes_read; enum { STATE_PREPARE, STATE_AIO_WAIT, STATE_IO_DONE, STATE_KV_QUEUED, STATE_KV_COMMITTING, STATE_KV_DONE, STATE_FINISHING, STATE_DONE } state; };
|
7.3 事务提交流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| _txc_add_transaction(txc) │ ▼ _txc_prepare(txc) ├─► 更新Onode元数据 ├─► 更新ExtentMap ├─► 更新Blob元数据 ├─► 更新FreelistManager └─► 准备RocksDB事务 │ ▼ _txc_submit_aio(txc) └─► 提交所有AIO到块设备 │ ▼ _txc_aio_wait(txc) └─► 等待所有AIO完成 │ ▼ _txc_commit_kv(txc) └─► 提交RocksDB事务 │ ▼ _txc_finish(txc) ├─► 更新缓存状态 ├─► 释放资源 └─► 更新统计信息
|
空间管理
8.1 分配流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 需要分配空间 │ ▼ Allocator::allocate() │ ├─► 查找空闲extent │ ├─► StupidAllocator: 线性搜索 │ ├─► BitmapAllocator: 位图查找 │ ├─► AvlAllocator: AVL树查找 │ └─► BtreeAllocator: B树查找 │ ├─► 选择最佳extent │ └─► 考虑hint、连续性等 │ └─► 返回分配的extent列表 │ ▼ FreelistManager::allocate() └─► 更新RocksDB中的空闲列表
|
8.2 释放流程
1 2 3 4 5 6 7 8 9 10 11 12 13
| 需要释放空间 │ ▼ Allocator::release() │ ├─► 将extent标记为空闲 │ └─► 更新分配器内部结构 │ └─► 合并相邻空闲extent(可选) │ ▼ FreelistManager::release() └─► 更新RocksDB中的空闲列表
|
8.3 碎片整理
BlueStore支持在线碎片整理:
- 识别碎片:扫描Blob,识别碎片化区域
- 迁移数据:将数据迁移到连续区域
- 更新映射:更新ExtentMap
- 释放旧空间:释放原来的extent
缓存机制
8.1 Onode缓存
目的:缓存对象的元数据(Onode)
实现:
- 使用LRU策略
- 分片缓存(减少锁竞争)
- 支持固定(pinned)Onode
缓存结构:
1 2 3 4 5
| struct OnodeCacheShard { ceph::mutex lock; LRUOnodeCache cache; map<ghobject_t, OnodeRef> pinned; };
|
8.2 Buffer缓存
目的:缓存对象数据
实现:
- 使用PriorityCache
- 支持多级缓存
- 支持写回缓存
缓存状态:
- CLEAN:数据与磁盘一致
- WRITING:正在写入
- DIRTY:数据已修改,待写入
8.3 缓存策略
- 读缓存:读取的数据加入缓存
- 写缓存:小写先写入缓存
- 预读:预测性读取
- 淘汰:LRU淘汰策略
压缩和校验
9.1 压缩
支持的算法:
- snappy:快速压缩
- zlib:标准压缩
- lz4:快速压缩
- zstd:高性能压缩
压缩流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 写入数据 │ ▼ 尝试压缩 │ ├─► 压缩率检查 │ └─► 如果压缩率 < threshold,使用压缩 │ ├─► 压缩数据 │ └─► 使用选择的压缩算法 │ └─► 存储压缩数据 ├─► 设置compressed_length └─► 设置compression算法
|
压缩配置:
bluestore_compression_algorithm:压缩算法
bluestore_compression_min_blob_size:最小压缩大小
bluestore_compression_max_blob_size:最大压缩大小
bluestore_compression_required_ratio:压缩率要求
9.2 校验和
支持的算法:
- crc32c:CRC32校验
- xxhash32:XXHash校验
- xxhash64:XXHash64校验
校验和流程:
1 2 3 4 5 6 7 8 9 10
| 写入数据 │ ▼ 计算校验和 │ ├─► 按块计算(每64KB一个) │ └─► 块大小由csum_chunk_order决定 │ └─► 存储校验和 └─► 存储在Blob元数据中
|
读取验证:
1 2 3 4 5 6 7 8 9
| 读取数据 │ ▼ 验证校验和 │ ├─► 读取数据块 ├─► 计算校验和 ├─► 与存储的校验和比较 └─► 如果不匹配,返回EIO错误
|
总结
核心优势
- 高性能:直接操作块设备,避免文件系统开销
- 灵活性:支持多种分配算法和压缩算法
- 可靠性:支持校验和、事务、写时复制
- 可扩展性:支持多设备、大容量
关键设计决策
- 元数据与数据分离:元数据存储在RocksDB,数据直接存储在块设备
- 写时分配:写入时分配空间,支持延迟分配
- 多级缓存:Onode缓存和Buffer缓存
- 异步I/O:使用AIO提高并发性能
适用场景
- SSD存储:针对SSD优化
- 高性能要求:需要低延迟、高IOPS
- 大容量存储:支持PB级存储
- 云存储:适合云环境部署
参考资料
- Ceph源码:
cephMain/src/os/bluestore/
- BlueStore文档:Ceph官方文档
- RocksDB文档:https://rocksdb.org/
正在加载留言…