Ceph BlueStore Write Analyse

栏目: 服务器 · 发布时间: 6年前

内容简介:Ceph从Luminous开始,默认使用了全新的存储引擎BlueStore,来替代之前提供存储服务的FileStore,与FileStore不一样的是,BlueStore直接管理裸盘,分配数据块来存储RADOS里的objects。Bluestore比较复杂,学习BlueStore的关键就是查看其实现的 ”object → block device“ 映射,所以本文先重点分析下该部分:一个Object写到Bluestore的处理过程。下面借用

Ceph从Luminous开始,默认使用了全新的存储引擎BlueStore,来替代之前提供存储服务的FileStore,与FileStore不一样的是,BlueStore直接管理裸盘,分配数据块来存储RADOS里的objects。

Bluestore比较复杂,学习BlueStore的关键就是查看其实现的 ”object → block device“ 映射,所以本文先重点分析下该部分:一个Object写到Bluestore的处理过程。

Bluestore整体架构

下面借用 Sage Weil 的图描述下BlueStore的整体架构:

Ceph BlueStore Write Analyse

里面的几个关键组件介绍:

  1. RocksDB:存储元数据信息
  2. BlueRocksEnv:提供RocksDB的访问接口
  3. BlueFS:实现BlueRocksEnv里的访问接口
  4. Allocator:磁盘分配器

针对BlueStore的整体架构不做展开,大家只需对其几大组件有些了解即可,本文继续介绍Object写操作到底层BlockDevice的过程。

BlueStore中Object到底层Device的映射关系

这里先从整体上给出在BlueStore中,一个Object的数据映射到底层BlockDevice的实现,如下图:

Ceph BlueStore Write Analyse

首先详细介绍下与上诉映射关系相关的数据结构。

Bluestore相关数据结构

BlueStore里与Object 数据映射相关的数据结构罗列如下:

Onode

任何RADOS里的一个Object都对应Bluestore里的一个Onode(内存结构),定义如下:

struct Onode {
    Collection *c;              // 对应的Collection,对应PG
    ghobject_t oid;             // Object信息
    bluestore_onode_t onode;    // Object存到kv DB的元数据信息
    ExtentMap extent_map;       // 映射lextents到blobs
};

通过Onode里的ExtentMap来查询Object数据到底层的映射。

ExtentMap

ExtentMapExtent 的set集合,是有序的,定义如下:

struct ExtentMap {
    Onode *onode;                   // 指向Onode指针
    extent_map_t extent_map;        // Extents到Blobs的map
    blob_map_t spanning_blob_map;   // 跨越shards的blobs
 
    struct Shard {
        bluestore_onode_t::shard_info *shard_info = nullptr;
        unsigned extents = 0;  ///< count extents in this shard
        bool loaded = false;   ///< true if shard is loaded
        bool dirty = false;    ///< true if shard is dirty and needs reencoding
    };
     mempool::bluestore_cache_other::vector<Shard> shards;    ///< shards
};

ExtentMap还提供了分片功能,防止在文件碎片化严重,ExtentMap很大时,影响写RocksDB的性能。

ExtentMap 会随着写入数据的变化而变化;

ExtentMap 的连续小段会合并为大;

覆盖写也会导致 ExtentMap 分配新的Blob;

Extent

Extent是实现object的数据映射的关键数据结构,定义如下:

struct Extent : public ExtentBase {
    uint32_t logical_offset = 0;    // 对应Object的逻辑偏移
    uint32_t blob_offset = 0;       // 对应Blob上的偏移
    uint32_t length = 0;            // 数据段长度
    BlobRef  blob;                  // 指向对应Blob的指针
};

每个Extent都会映射到下一层的Blob上,Extent会依据 block_size 对齐,没写的地方填充全零。

Extent中的 length 值,最小:block_size,最大:max_blob_size

Blob

Blob是Bluestore里引入的处理块设备数据映射的中间层,定义如下:

struct Blob {
    int16_t id = -1;
    SharedBlobRef shared_blob;      // 共享的blob状态
    mutable bluestore_blob_t blob;  // blob的元数据
};
struct bluestore_blob_t {
    PExtentVector extents;          // 对应磁盘上的一组数据段
    uint32_t logical_length = 0;    // blob的原始数据长度
    uint32_t compressed_length = 0; // 压缩的数据长度
};

每个Blob会对应一组 PExtentVector,它就是 bluestore_pextent_t 的一个数组,指向从Disk中分配的物理空间。

Blob里可能对应一个磁盘pextent,也可能对应多个pextent;

Blob里的pextent个数最多为:max_blob_size / min_alloc_size;

Blob里的多个pextent映射的Blob offset可能不连续,中间有空洞;

AllocExtent

AllocExtent是管理物理磁盘上的数据段的,定义如下:

struct bluestore_pextent_t : public AllocExtent {
    ...
};
class AllocExtent {
public:
    uint64_t offset;  // 磁盘上的物理偏移
    uint32_t length;  // 数据段的长度
...
};

AllocExtent的 length 值,最小:min_alloc_size,最大:max_blob_size

BlueStore写数据流程

BlueStore里的写数据入口是 BlueStore::_do_write() ,它会根据 min_alloc_size 来切分 [offset, length] 的写,然后分别依据 small write 和 big write 来处理,如下:

// 按照min_alloc_size大小切分,把写数据映射到不同的块上
          [offset, length]
          |==p1==|=======p2=======|=p3=|
|----------------|----------------|----------------|
| min_alloc_size | min_alloc_size | min_alloc_size |
|----------------|----------------|----------------|
small write: p1, p3
big   write: p2
 
 
BlueStore::_do_write()
|-- BlueStore::_do_write_data()
|   // 依据`min_alloc_size`把写切分为`small/big`写
|   | -- BlueStore::_do_write_small()
|   |    | -- BlueStore::ExtentMap::seek_lextent()
|   |    | -- BlueStore::Blob::can_reuse_blob()
|   |         reuse blob? or new blob?
|   |    | -- insert to struct WriteContext {};
|   | -- BlueStore::_do_write_big()
|   |    | -- BlueStore::ExtentMap::punch_hole()
|   |    | -- BlueStore::Blob::can_reuse_blob()
|   |         reuse blob? or new blob?
|   |    | -- insert to struct WriteContext {};
|-- BlueStore::_do_alloc_write()
|   | -- StupidAllocator::allocate()
|   | -- BlueStore::ExtentMap::set_lextent()
|   | -- BlueStore::_buffer_cache_write()
|-- BlueStore::_wctx_finish()

BlueStore Log分析

可以通过开启Ceph bluestore debug来抓取其写过程中对数据的映射,具体步骤如下。

下面通过在CephFS上测试为例:

1. 创建一个文件
# touch tstfile
 
 
2. 查看该文件的inode numer
# ls -i
2199023255554 tstfile
 
 
3. 获取该文件的映射信息
上诉inode number转换为16进制:20000000002
查看文件的第一个默认4M Object的映射信息
# ceph osd map cephfs_data_ssd 20000000002.00000000
osdmap e2649 pool 'cephfs_data_ssd' (3) object '20000000002.00000000' -> pg 3.3ff3fe94 (3.94) -> up ([12,0], p12) acting ([12,0], p12)
 
 
4. 在osd 12上开启bluestroe debug信息
# ceph daemon /var/run/ceph/ceph-osd.12.asok config set debug_bluestore "30"  // 开启debug
# ceph daemon /var/run/ceph/ceph-osd.12.asok config set debug_bluestore "1/5" // 恢复默认
 
 
5. 对测试文件的前4M内进行dd操作,收集log
# dd if=/dev/zero of=tstfile bs=4k count=1 oflag=direct
# grep -v "trim shard target" /var/log/ceph/ceph-osd.12.log | grep -v "collection_list" > bluestore-write-0-4k.log

通过上述方式可以搜集到Bluestore在写入数据时,object的数据分配和映射过程,可以帮助理解其实现。

BlueStore dd write各种case

为了更好的理解BlueStore里一个write的过程,我们通过 dd 命令写一个Object,然后抓取log后分析不同情况下的Object数据块映射情况,最后结果如下图所示:

Ceph BlueStore Write Analyse

注释:上图的数据块映射关系是通过抓取log后获取的。

最后一图中,写[100k, 200)的区域,查看Object对应的ExtentMap并不是与 min_alloc_size(16k)对齐的,只是保证是block_size(4k)对齐而已。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

知识发现

知识发现

史忠植 / 2011-1 / 59.00元

《知识发现(第2版)》全面而又系统地介绍了知识发现的方法和技术,反映了当前知识发现研究的最新成果和进展。全书共分15章。第1章是绪论,概述知识发现的重要概念和发展过程。下面三章重点讨论分类问题,包括决策树、支持向量机和迁移学习。第5章阐述聚类分析。第6章是关联规则。第7章讨论粗糙集和粒度计算。第8章介绍神经网络,书中着重介绍几种实用的算法。第9章探讨贝叶斯网络。第10章讨论隐马尔可夫模型。第11章......一起来看看 《知识发现》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具