目录
- 未完待续
 - 前言
 - 组成
 - 前期准备工作
 - 基础概念
 - 对象
 - Pextent
 - extent
 - Blob
 - Node
 
- 线程
 - 事务
 - 磁盘的抽象与分配
 - 位图法
 - 分层位图
 
- 上电流程
 - 写流程
 - 读流程
 - 参考资料
 
未完待续
前言
BlueStore是什么?
 Ceph是一个统一的分布式存储系统。BlueStore是Ceph的存储引擎。
 它的作用是什么?
 存储引擎的作用还能是什么?把Ceph上层交给他的数据安稳的存储在磁盘上,需要的时候再读出来或者删除。这就是他的作用。
组成

 如上图,BlueStore由下面接模块构成:
- RocksDB:为BlueStore提供kv存储。
 - BlueFs:RocksDB是一个持久化的kv存储系统,但是Rocksdb本身又不能直接操作磁盘读写数据,在这个情况下,BlueFS就承担了这个职责,作为一个文件系统,为RocksDB提供了磁盘上文件的读写能力。
 - BlueRocksEnv:在RocksDB与BlueFS间提供一个桥梁。
 - Allocator:磁盘的空间管理器。
 - BlockDevice:以HDD或者SSD为代表的裸盘
从上图我们可以看到,对于用户数据本身是由BlueStore直接操作裸盘进行读写,但是对于用户数据的元数据,是通过RocksDB进行读写的。 
前期准备工作
在开始研究BlueStore的工作流程前,咱们先了解一下必要的知识。
基础概念
对象
咱们尽量从一个实际的例子进行说明。假定我需要存储《流浪地球2》这个电影,电影本身是20个GB。在Ceph里,会把这个20GB的文件切分成2MB(或者4BM,参数,可配)的一个个文件块,我们把这个文件块就叫做对象。而在BlueStore这一层,是感知不到20GB的《浏览地球2》,它只能感知到2MB的对象块。
Pextent
struct bluestore_pextent_t {
    // 磁盘上的物理偏移
    uint64_t offset = 0;
    // 数据段的长度
    uint32_t length = 0;
}
 
Pextent就是代表真实的物理磁盘上的一个区间。offset就是相对于磁盘上起始位置的偏移量,length的单位就是字节。
extent
struct Extent {
    // 对象内逻辑偏移,不需要块对齐。
    uint32_t logical_offset = 0;
    // 逻辑段长度,不需要块对齐。
    uint32_t length = 0;
    // 当logical_offset是块对齐时,blob_offset始终为0;
    // 不是块对齐时,将逻辑段内的数据通过Blob映射到磁盘物理段会产生物理段内的偏移称为blob_offset。
    uint32_t blob_offset = 0;
	// 多个物理块
	BlobRef  blob; 
  
}
 
对于那个2MB的对象,在BlueStore里,也会对他进行逻辑切分。假定把2MB的对象切分成3块,第一块512KB,第二块512KB,第二块1024KB,那么
 第一个Extent的logical_offset 是0,length是512x1024
 第二个Extent的logical_offset是1x512x1024,length是512x1024
 第三个Extent的logical_offset是2x512x1024,length是1024x1024
 上面还有blob_offset 的概念,牵扯到块对其,大家暂时忽略。
Blob
在上面的Extent里面还有一个Blob是什么意思?
 就上面那个例子,在真实的物理磁盘上,不一定有一块连续的空闲的1MB的空间。所以BlueStore会把物理上不在一块的磁盘空间逻辑上放到一块。
struct Blob {
    // reference count
    std::atomic_int nref = {0};
    mutable vector<bluestore_pextent_t> blob;
}
 
一个512KB的Blob,内部可能是磁盘上3个并不相连的空间段拼起来的。
Node
// 内存数据结构
struct Onode {
    // reference count
    std::atomic_int nref;
    // onode 对应的PG
    Collection *c;
    // onode磁盘数据结构
    bluestore_onode_t onode;
    // 有序的Extent逻辑空间集合,持久化在RocksDB。lexetnt--->blob
    ExtentMap extent_map;
    ......
}
// 磁盘数据结构 onode: per-object metadata
struct bluestore_onode_t {
    // 逻辑ID,单个BlueStore内部唯一。
    uint64_t nid = 0;
    // 对象大小
    uint64_t size = 0;
    // 对象扩展属性
    map<mempool::bluestore_cache_other::string, bufferptr> attrs;
    ......
}
 
上面的Onode 描述一个对象(就是那个2M的对象)的信息。
 上面的ExtentMap,大家猜一下也能知道,假定一个对象被分成了3个Extent,那都是哪3个Extent呢,对象本身得知道,自己的数据逻辑上分成了哪几块么。
线程
事务
磁盘的抽象与分配
位图法
BlueStore面对的一块完完全全的裸盘。那么第一个问题就是,BlueStore怎么知道磁盘上那一块用了,哪一块没有用呢。
 首先对磁盘进行分块,假定就按照4KB分块。
 其实一个思路就是先把磁盘上的块进行编号,然后对于每个块使用一个比特的0代表已经被使用,1代表没有使用。这样以来我只要使用原始硬盘空间的32768分之1的空间就能描述磁盘里每个区域的使用情况了(410248=32768)
 那么一个100GB的磁盘,大概只需要32MB的内存比特流就能描述。
 以上,就叫做位图法。
分层位图
以上面的例子来说,假如我需要在1块100GB的磁盘上分配一个4KB的块,最最极端情况下,我就得扫描32MB的数据,才能知道哪个块没有被使用。这个是不可接受的。
 大家知道跳表么?
 还是那个100GB的空间,我假定L0层就是32MB的内存块。
 我在L1层申请64KB的内存块,L1的一个比特对应L0层的512个比特。
 假定L0的前512个比特都是0(代表磁盘上前5124KB的一段区域都已经被分配了)那么我L1上第1个比特就是0。
 假定L0的前512个比特不都是0(代表磁盘上5124KB的一段区域还没有被完全分配完)那么我L1上第1个比特就是1。
 如果磁盘空间更大了,那么L1上面还可以加一个L2。
 这样以来,分配空闲磁盘的时间复杂度就可控了。
上电流程
写流程
读流程
参考资料
https://zhuanlan.zhihu.com/p/68067068
 https://zhuanlan.zhihu.com/p/92397191


![[机器学习]LFM梯度下降算法](https://img-blog.csdnimg.cn/direct/aa6c295d2beb4186bbe2ff5d40327929.png)







![[office] excel表格怎么绘制股票的CCI指标- #媒体#学习方法#笔记](https://img-blog.csdnimg.cn/img_convert/1ebb79143684ee3abb3d1201b0417670.jpeg)





![[基础IO]文件描述符{重定向/perror/磁盘结构/inode/软硬链接}](https://img-blog.csdnimg.cn/direct/5961092a4bec43fd8072e0f2d69da3ed.png)


