Ceph BlueStore 分配器深度解析
目录
1. 引言
在 Ceph 存储系统中,BlueStore 作为新一代对象存储引擎,直接管理裸块设备,摒弃了传统文件系统的开销。在这种架构下,分配器(Allocator) 成为了至关重要的组件——它负责管理磁盘空闲空间的分配和回收,直接影响着存储性能、碎片化程度和内存占用。
本文将深入剖析 Ceph 分配器的设计原理、实现细节和使用场景,帮助你全面理解这一核心组件。
本文适合谁?
- Ceph 运维工程师:了解如何选择和调优分配器
 
- 存储开发者:理解分配器的设计思想和实现细节
 
- 系统架构师:评估不同分配器对系统的影响
 
2. 为什么需要分配器
2.1 BlueStore 的存储架构
在 BlueStore 中,数据流转路径如下:
1 2 3 4 5 6 7 8 9
   | 用户写入对象     ↓ BlueStore 接收请求     ↓ Allocator 分配磁盘空间 ← 本文重点     ↓ 写入裸块设备     ↓ 元数据存储到 RocksDB
   | 
 
BlueStore 直接管理裸设备,需要自己实现:
- 空闲空间管理:哪些磁盘块是空闲的?
 
- 空间分配:为新数据找到合适的存储位置
 
- 空间回收:删除数据后回收磁盘块
 
- 碎片管理:避免磁盘空间碎片化
 
这就是分配器的职责所在。
2.2 分配器的核心问题
分配器需要解决以下关键问题:
问题 1:如何高效查找空闲空间?
- 对于 10TB 磁盘,有数百万个 4KB 块
 
- 需要快速找到满足大小要求的连续空间
 
问题 2:如何控制内存占用?
- 记录所有空闲区间需要内存
 
- 碎片越多,内存占用越大
 
- 需要在性能和内存间平衡
 
问题 3:如何减少碎片?
问题 4:如何保证并发性能?
3. 分配器架构设计
3.1 核心接口
Ceph 定义了统一的分配器接口:
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
   | class Allocator { public:      virtual int64_t allocate(     uint64_t want_size,           uint64_t alloc_unit,          uint64_t max_alloc_size,      int64_t hint,                 PExtentVector *extents      ) = 0;
       virtual void release(     const interval_set<uint64_t>& release_set   ) = 0;
       virtual uint64_t get_free() = 0;
       virtual double get_fragmentation() = 0;
       virtual void init_add_free(uint64_t offset, uint64_t length) = 0;
       virtual void init_rm_free(uint64_t offset, uint64_t length) = 0; };
  | 
 
3.2 关键数据结构
Extent(区段)
表示一段连续的磁盘空间:
1 2 3 4 5 6
   | struct bluestore_pextent_t {   uint64_t offset;     uint64_t length;   };
  typedef std::vector<bluestore_pextent_t> PExtentVector;
  | 
 
分配示例
1 2 3 4 5 6
   | 磁盘布局:[已用][  空闲100MB  ][已用][  空闲50MB  ]
  分配 60MB:   - 查找:找到 100MB 空闲块   - 分配:[offset: 1000MB, length: 60MB]   - 更新:剩余 [offset: 1060MB, length: 40MB] 标记为空闲
   | 
 
3.3 工作流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | ┌─────────────────────────────────────────────────────────┐ │                      BlueStore                          │ │                                                         │ │  写入对象 ──┐                                           │ │            │                                            │ │            ↓                                            │ │  ┌──────────────────┐        ┌──────────────────┐     │ │  │   Allocator      │◄──────►│  FreelistManager │     │ │  │                  │        │   (RocksDB)      │     │ │  │ • 内存中管理     │        │  持久化空闲信息   │     │ │  │ • 快速分配       │        │                  │     │ │  └──────────────────┘        └──────────────────┘     │ │            │                                            │ │            ↓                                            │ │  ┌──────────────────┐                                  │ │  │   Block Device   │                                  │ │  │   (裸块设备)     │                                  │ │  └──────────────────┘                                  │ └─────────────────────────────────────────────────────────┘
   | 
 
关键点:
- Allocator:内存中管理,性能关键路径
 
- FreelistManager:持久化到 RocksDB,重启时恢复
 
4. 五种分配器实现详解
Ceph 提供了 5 种分配器实现,每种都有不同的设计权衡。
4.1 StupidAllocator(简单分配器)
设计原理
StupidAllocator 使用 interval_set 结构,按大小分桶(bin)管理空闲块:
1 2 3 4 5 6 7 8 9
   | class StupidAllocator : public Allocator {      std::vector<interval_set_t> free;                };
  | 
 
分配策略
- 根据请求大小计算 bin
 
- 从对应 bin 中查找
 
- 找不到则去更大的 bin
 
- Simple first-fit 策略
 
优缺点
优点:
缺点:
适用场景: 测试、开发环境
4.2 BitmapAllocator(位图分配器)
设计原理
使用 位图(Bitmap) 表示每个分配单元的状态:
1 2 3 4 5 6 7 8 9 10 11
   | 磁盘划分:每 4KB 一个分配单元
  位图表示: Bit:    0  1  2  3  4  5  6  7  8  9  10 11 12 状态:   已 空 空 空 已 已 空 空 空 空 已 空 空        用 闲 闲 闲 用 用 闲 闲 闲 闲 用 闲 闲
  分配 16KB (4个单元):   - 扫描位图找到连续的 4 个 1   - 位置 6-9 可用   - 标记为已用:...00000111...
   | 
 
数据结构
1 2 3 4 5 6 7
   | class BitmapAllocator : public Allocator,   public AllocatorLevel02<AllocatorLevel01Loose> {             };
   | 
 
分配策略
- 在 L1 位图快速定位可能的空闲区域
 
- 在 L2 位图精确查找连续空闲块
 
- 利用位运算加速查找
 
优缺点
优点:
- ✅ 内存占用可预测:O(设备大小/分配单元)
- 10TB 设备,4KB 单元 → 320MB 内存
 
 
- ✅ 查找快速:位运算高效
 
- ✅ 碎片处理好
 
缺点:
适用场景:
- ✅ SSD 设备
 
- ✅ 小文件负载
 
- ✅ 内存充足场景
 
4.3 AvlAllocator(AVL 树分配器)
设计原理
使用 两棵 AVL 树 管理空闲区间:
1 2 3 4 5 6 7 8 9 10 11 12
   | struct range_seg_t {   uint64_t start;     uint64_t end;     };
  class AvlAllocator : public Allocator {      avl_set<range_seg_t, by_offset> range_tree;         avl_multiset<range_seg_t, by_size> range_size_tree; };
  | 
 
可视化示例
1 2 3 4 5 6 7 8 9 10 11 12
   | 空闲区间:  
  range_tree (按偏移):                   /         \        
  range_size_tree (按大小):            100MB         /         \             100MB         200MB
   | 
 
动态分配策略
1 2 3 4 5 6 7 8 9 10 11 12 13
   |  if (free_space_pct > threshold) {         search_by_offset(range_tree, cursor); }
 
  else {         search_by_size(range_size_tree, want_size); }
 
  | 
 
优缺点
优点:
- ✅ 动态策略:根据空闲度自动调整
 
- ✅ 性能均衡:O(log N) 查找时间
 
- ✅ 碎片控制好
 
- ✅ 生产环境推荐
 
缺点:
- ❌ 内存不可控:碎片多时占用高
 
- ❌ 高碎片下性能下降
 
适用场景:
4.4 BtreeAllocator(B 树分配器)
设计原理
与 AvlAllocator 类似,但使用 B-tree 替代 AVL 树:
1 2 3 4 5
   | class BtreeAllocator : public Allocator {      btree::btree_map<uint64_t, range_seg_t> range_tree;   btree::btree_multimap<uint64_t, range_seg_t> range_size_tree; };
  | 
 
B-tree vs AVL
1 2 3 4 5 6 7 8 9 10 11
   | AVL Tree (二叉树):        [50]       /    \    [30]    [70]    /  \    /  \ [20][40][60][80]
  B-tree (多叉树):     [30 | 60]     /    |    \ [10,20][40,50][70,80,90]
   | 
 
优缺点
优点:
- ✅ 更好的缓存局部性:节点存储多个元素
 
- ✅ 树高度更低:减少指针跳转
 
- ✅ 大规模数据性能好
 
缺点:
适用场景:
4.5 HybridAllocator(混合分配器)⭐ 推荐
设计原理
结合 AVL 和 Bitmap 的优势,控制内存占用:
1 2 3 4 5 6 7 8 9 10
   | class HybridAllocator : public AvlAllocator {   uint64_t max_mem;           BitmapAllocator* bitmap;       virtual void _spillover_range(uint64_t start, uint64_t end) override {               bitmap->init_add_free(start, end);   } };
  | 
 
工作流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | ┌─────────────────────────────────────────────┐ │           HybridAllocator                   │ │                                             │ │  ┌─────────────────────────┐               │ │  │   AVL Tree (in-memory)  │               │ │  │   存储大空闲块           │  内存 < 256MB │ │  │   [1GB-2GB]             │               │ │  │   [5GB-6GB]             │               │ │  │   ...                   │               │ │  └─────────────────────────┘               │ │              ↓ 溢出                         │ │  ┌─────────────────────────┐               │ │  │   Bitmap (spillover)    │               │ │  │   存储小碎片块           │               │ │  │   [4KB] [8KB] [12KB]... │               │ │  └─────────────────────────┘               │ └─────────────────────────────────────────────┘
  分配逻辑: 1. 优先从 AVL 树分配(快速) 2. 找不到则查询 Bitmap 3. 定期整理:Bitmap 中大块合并回 AVL
   | 
 
内存控制策略
1 2 3 4 5 6 7 8 9
   |  bluestore_hybrid_alloc_mem_cap = 268435456
 
  if (range_tree.size() >= max_ranges) {      auto smallest = range_size_tree.begin();   spillover_to_bitmap(smallest); }
 
  | 
 
优缺点
优点:
- ✅ 内存可控:设置上限,可预测
 
- ✅ 性能优秀:大块分配快速(AVL)
 
- ✅ 碎片处理好:小碎片交给 Bitmap
 
- ✅ 生产环境首选 ⭐⭐⭐
 
缺点:
适用场景:
- ✅ 所有生产环境 🏆
 
- ✅ 大规模部署
 
- ✅ 混合负载
 
5. 性能对比与选择
5.1 综合对比表
| 分配器 | 
内存占用 | 
分配速度 | 
碎片处理 | 
复杂度 | 
生产推荐 | 
| Stupid | 
中等 | 
⭐⭐ | 
⭐⭐ | 
简单 | 
❌ 仅测试 | 
| Bitmap | 
固定(高) | 
⭐⭐⭐⭐ | 
⭐⭐⭐⭐ | 
中等 | 
✅ SSD | 
| AVL | 
动态 | 
⭐⭐⭐ | 
⭐⭐⭐⭐ | 
中等 | 
✅ 通用 | 
| Btree | 
动态 | 
⭐⭐⭐ | 
⭐⭐⭐⭐ | 
高 | 
✅ 大设备 | 
| Hybrid | 
可控 | 
⭐⭐⭐⭐⭐ | 
⭐⭐⭐⭐⭐ | 
高 | 
✅✅ 首选 | 
5.2 选择建议
决策树
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | 开始  │  ├─ 测试/开发环境?  │   └─ 是 → StupidAllocator  │  ├─ 内存严格受限?  │   └─ 是 → HybridAllocator (设置 mem_cap)  │  ├─ 设备类型?  │   ├─ SSD + 小文件负载 → BitmapAllocator  │   ├─ 大设备 (>20TB) → BtreeAllocator  │   └─ 其他 → HybridAllocator ⭐  │  └─ 不确定?→ HybridAllocator (默认推荐)
   | 
 
场景推荐
场景 1:高性能 SSD 集群
1 2
   | bluestore_allocator = hybrid bluestore_hybrid_alloc_mem_cap = 536870912  
   | 
 
场景 2:HDD 大容量存储
1
   | bluestore_allocator = btree
   | 
 
场景 3:内存受限环境
1 2
   | bluestore_allocator = hybrid bluestore_hybrid_alloc_mem_cap = 134217728  
   | 
 
6. 源码解析
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   |  int BlueStore::_do_alloc_write(     TransContext *txc,     CollectionRef& c,     OnodeRef o,     BlueStore::WriteContext *wctx) {   uint64_t need = wctx->logical_length;         PExtentVector extents;   int64_t got = alloc->allocate(     need,                         min_alloc_size,               need,                         0,                            &extents                    );      if (got < 0) {          return got;   }         for (auto& p : extents) {     r = bdev->aio_write(       p.offset,                     bl,                           &txc->ioc,                   false     );   }         o->extent_map.punch_hole(offset, length);   o->extent_map.add_extent(offset, extents);      return 0; }
 
  | 
 
6.2 AVL 分配器核心代码
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 42 43 44 45 46 47 48 49 50 51 52 53
   |  int64_t AvlAllocator::_allocate(     uint64_t want,     uint64_t unit,     uint64_t max_alloc_size,     int64_t  hint,     PExtentVector *extents) {   std::lock_guard<std::mutex> l(lock);      uint64_t allocated = 0;      while (allocated < want) {     uint64_t offset, length;               if (_use_first_fit()) {              offset = _pick_block_after(&cursor, want - allocated, unit);     } else {              offset = _pick_block_fits(want - allocated, unit);     }          if (offset == 0) {       break;       }               _remove_from_tree(offset, length);               extents->emplace_back(offset, length);     allocated += length;   }      return allocated; }
 
  uint64_t AvlAllocator::_pick_block_fits(uint64_t size, uint64_t align) {      range_seg_t search_node(0, size);   auto rs_it = range_size_tree.lower_bound(search_node);      if (rs_it == range_size_tree.end()) {     return 0;     }      uint64_t offset = p2roundup(rs_it->start, align);   return offset; }
 
  | 
 
6.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
   |  Allocator *Allocator::create(     CephContext* cct,     std::string_view type,     int64_t size,     int64_t block_size,     std::string_view name) {   Allocator* alloc = nullptr;      if (type == "stupid") {     alloc = new StupidAllocator(cct, size, block_size, name);   } else if (type == "bitmap") {     alloc = new BitmapAllocator(cct, size, block_size, name);   } else if (type == "avl") {     alloc = new AvlAllocator(cct, size, block_size, name);   } else if (type == "btree") {     alloc = new BtreeAllocator(cct, size, block_size, name);   } else if (type == "hybrid") {     uint64_t mem_cap = cct->_conf.get_val<uint64_t>(       "bluestore_hybrid_alloc_mem_cap"     );     alloc = new HybridAllocator(cct, size, block_size, mem_cap, name);   }      return alloc; }
 
  | 
 
7. 最佳实践
7.1 配置优化
基础配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | 
  [osd]
  bluestore_allocator = hybrid
 
  bluestore_hybrid_alloc_mem_cap = 268435456
 
  bluestore_min_alloc_size_hdd = 65536 bluestore_min_alloc_size_ssd = 4096
 
  bluestore_avl_alloc_ff_max_search_count = 100 bluestore_avl_alloc_ff_max_search_bytes = 1048576
 
  | 
 
高性能 SSD 配置
1 2 3 4
   | [osd] bluestore_allocator = hybrid bluestore_hybrid_alloc_mem_cap = 536870912   bluestore_min_alloc_size_ssd = 4096
   | 
 
大容量 HDD 配置
1 2 3
   | [osd] bluestore_allocator = btree bluestore_min_alloc_size_hdd = 65536
   | 
 
7.2 监控指标
查看分配器状态
1 2 3 4 5 6 7 8 9 10 11 12 13
   |  ceph daemon osd.0 bluestore allocator dump
 
  {     "allocator_type": "hybrid",     "capacity": 10737418240,     "alloc_unit": 4096,     "alloc_size_min": 4096,     "free": 8589934592,     "fragmentation": 0.15,     "num_free_ranges": 12450 }
 
  | 
 
关键指标
1 2 3 4 5 6 7 8
   |  fragmentation_score = num_free_ranges / (free_blocks - 1)
 
  utilization = (capacity - free) / capacity
 
  alloc_success_rate = allocated / requested
 
  | 
 
Prometheus 监控
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  groups: - name: ceph_allocator   rules:      - alert: HighFragmentation     expr: ceph_bluestore_fragmentation > 0.3     for: 10m     annotations:       summary: "OSD {{ $labels.osd }} fragmentation high"             - alert: LowFreeSpace     expr: ceph_bluestore_free_bytes / ceph_bluestore_capacity_bytes < 0.1     for: 5m
 
  | 
 
7.3 性能调优
调优步骤
1. 基线测试
1 2 3 4
   |  fio --name=test --ioengine=libaio --direct=1 \     --bs=4k --rw=randwrite --numjobs=4 \     --size=10G --runtime=300
 
  | 
 
2. 调整分配器
1 2 3 4 5 6
   |  ceph config set osd.* bluestore_allocator hybrid ceph config set osd.* bluestore_hybrid_alloc_mem_cap 536870912
 
  systemctl restart ceph-osd@0
 
  | 
 
3. 压力测试
1 2 3 4 5
   |  rbd bench --io-type write --io-size 4K --io-pattern rand test-pool/test-image
 
  rados bench -p test-pool 300 write -t 32
 
  | 
 
4. 对比结果
1 2 3
   |  ceph osd perf ceph daemon osd.0 perf dump
 
  | 
 
常见问题调优
问题 1:分配延迟高
1 2 3 4 5 6 7
   | 
 
  ceph config set osd.* bluestore_hybrid_alloc_mem_cap 1073741824  
 
  ceph config set osd.* bluestore_allocator bitmap
 
  | 
 
问题 2:内存占用过高
1 2 3 4 5 6 7
   | 
 
  ceph config set osd.* bluestore_hybrid_alloc_mem_cap 134217728  
 
  ceph osd compact <osd-id>
 
  | 
 
问题 3:碎片率过高
1 2 3 4 5 6 7 8 9 10 11
   | 
 
  systemctl stop ceph-osd@0 ceph-bluestore-tool --path /var/lib/ceph/osd/ceph-0 \                     fsck --deep
 
  ceph osd out osd.0
  ceph osd in osd.0
 
  | 
 
7.4 升级和迁移
在线切换分配器
1 2 3 4 5 6 7 8 9 10 11 12
   |  ceph config set osd.0 bluestore_allocator hybrid
 
  ceph osd set noout ceph osd set norebalance systemctl restart ceph-osd@0 ceph osd unset noout ceph osd unset norebalance
 
  ceph daemon osd.0 config get bluestore_allocator
 
  | 
 
批量迁移
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | #!/bin/bash
 
  for osd in $(ceph osd ls); do   echo "Processing OSD.$osd"         ceph config set osd.$osd bluestore_allocator hybrid         ceph osd set noout   systemctl restart ceph-osd@$osd         while ! ceph osd stat | grep -q "up $((osd+1))"; do     sleep 5   done      ceph osd unset noout   sleep 30   done
   | 
 
8. 问题排查
8.1 常见问题
问题 1:分配失败 (ENOSPC)
现象:
1 2
   | 客户端写入失败: No space left on device 但 ceph df 显示还有空间
   | 
 
原因:
- 碎片化严重,找不到连续空间
 
- 分配器内部数据结构不一致
 
排查步骤:
1 2 3 4 5 6 7 8
   |  ceph daemon osd.0 bluestore allocator dump | grep fragmentation
 
  ceph daemon osd.0 bluestore allocator dump | grep num_free_ranges
 
  tail -f /var/log/ceph/ceph-osd.0.log | grep -i "alloc\|enospc"
 
  | 
 
解决方案:
1 2 3 4 5 6 7 8 9 10
   |  ceph osd out 0 systemctl stop ceph-osd@0 ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-0 \                        --op compact systemctl start ceph-osd@0 ceph osd in 0
 
  bluestore_min_alloc_size_hdd = 131072  
 
  | 
 
问题 2:内存泄漏
现象:
1 2
   | OSD 内存持续增长 最终触发 OOM killer
   | 
 
排查步骤:
1 2 3 4 5 6 7
   |  ceph daemon osd.0 dump_mempools | grep bluestore_alloc
 
  ceph daemon osd.0 bluestore allocator dump | grep num_free_ranges
 
 
 
  | 
 
解决方案:
1 2 3 4 5 6
   |  systemctl restart ceph-osd@0
 
  ceph config set osd.0 bluestore_allocator hybrid ceph config set osd.0 bluestore_hybrid_alloc_mem_cap 268435456
 
  | 
 
问题 3:性能抖动
现象:
1 2
   | 写入延迟周期性升高 iostat 显示设备利用率不高
   | 
 
排查步骤:
1 2 3 4 5 6 7 8
   |  ceph daemon osd.0 perf dump | grep -A 5 bluestore_alloc
 
  ceph daemon osd.0 bluestore allocator dump
 
  ceph daemon osd.0 config set debug_bluestore 10
 
  | 
 
解决方案:
1 2 3
   |  ceph config set osd.* bluestore_avl_alloc_ff_max_search_count 50 ceph config set osd.* bluestore_avl_alloc_ff_max_search_bytes 524288
 
  | 
 
8.2 调试工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   |  ceph-bluestore-tool --path /var/lib/ceph/osd/ceph-0 \                     show-label
 
  ceph-bluestore-tool --path /var/lib/ceph/osd/ceph-0 \                     fsck --deep
 
  ceph-bluestore-tool --path /var/lib/ceph/osd/ceph-0 \                     free-dump
 
  ceph-bluestore-tool --path /var/lib/ceph/osd/ceph-0 \                     repair
 
  | 
 
性能分析
1 2 3 4 5 6 7 8
   |  perf record -g -p $(pidof ceph-osd) -- sleep 30 perf report --stdio | grep -A 10 Allocator
 
  gdb -p $(pidof ceph-osd) (gdb) thread apply all bt (gdb) print allocator->get_free()
 
  | 
 
9. 总结
9.1 核心要点
分配器是 BlueStore 的核心
 
五种实现,各有千秋
- Stupid: 测试用
 
- Bitmap: SSD 优化,内存固定
 
- AVL: 通用,动态平衡
 
- Btree: 大设备优化
 
- Hybrid: 生产首选 ⭐
 
 
关键权衡
- 性能 vs 内存
 
- 碎片控制 vs 分配速度
 
- 简单 vs 功能
 
 
实践建议
- 默认使用 Hybrid
 
- 监控碎片率和内存
 
- 定期整理碎片
 
- 根据负载调优
 
 
9.2 决策建议
1 2 3 4 5 6 7 8 9 10 11 12
   | 你应该使用哪个分配器?
  ┌─────────────────────────────────────┐ │  生产环境?                          │ │  ├─ 是 → Hybrid Allocator ⭐⭐⭐    │ │  └─ 否 → Stupid (测试) / AVL        │ └─────────────────────────────────────┘
  特殊场景: • 高性能 SSD + 内存充足 → Bitmap • 超大设备 (>20TB) → Btree • 内存严格受限 → Hybrid (设置 mem_cap)
   | 
 
9.3 未来展望
Ceph 社区正在持续优化分配器:
更智能的策略
- 基于 workload 的自适应分配
 
- 机器学习优化位置选择
 
 
更低的开销
 
更好的碎片控制
 
持久化内存支持
 
参考资料
源码
src/os/bluestore/Allocator.h - 分配器接口 
src/os/bluestore/*Allocator.cc - 各实现 
 
文档
 
论文
- “BlueStore: A New, Faster Storage Backend for Ceph”
 
 
社区
- Ceph Dev Mailing List
 
- #ceph-devel IRC
 
 
关于作者
by hoshi
本文基于 Ceph 最新代码(Pacific/Quincy 版本)分析编写,涵盖了分配器的设计原理、实现细节和最佳实践。
如果觉得本文有帮助,欢迎分享! 🚀
有任何问题或建议,欢迎提 Issue 。