Ceph的BlueStore总体介绍

整体架构

bluestore的诞生是为了解决filestore自身维护一套journal并同时还需要基于系统文件系统的写放大问题,并且filestore本身没有对SSD进行优化,因此bluestore相比于filestore主要做了两方面的核心工作:
  • 去掉journal,直接管理裸设备
  • 针对SSD进行单独优化
bluestore的整体架构如下图所示:
通过Allocator实现对裸设备的管理,直接将数据保存到设备上;同时针对metadata使用RocksDB进行保存,底层自行封装了一个BlueFS用来对接RocksDB与裸设备。
 

模块划分

核心模块

 

 

  • RocksDB: 存储预写式日志、数据对象元数据、Ceph的omap数据信息、以及分配器的元数据(分配器负责决定真正的数据应在什么地方存储)
  • BlueRocksEnv: 与RocksDB交互的接口
  • BlueFS: 小的文件系统,解决元数据、文件空间及磁盘空间的分配和管理,并实现了rocksdb::Env 接口(存储RocksDB日志和sst文件)。因为rocksdb常规来说是运行在文件系统的顶层,下面是BlueFS。 它是数据存储后端层,RocksDB的数据和BlueStore中的真正数据被存储在同一个块物理设备
  • HDD/SSD: 物理块设备,存储实际的数据
rocksdb本身是基于文件系统的,不是直接操作裸设备。它将系统相关的处理抽象成Env,用户可用实现相应的接口(rocksdb默认的Env是PosixEnv,直接对接本地文件系统)。BlueRocksEnv是bluestore实现的一个类,继承自rocksdb::EnvWrapper,来为rocksdb提供底层系统的封装。
 
为了对接BlueRocksEnv,实现了一个小的文件系统BlueFS,只实现rocksdb Env需要的接口。所有的元数据的修改都记录在BlueFS的日志中,也就是对于BlueFS,元数据的持久化保存在日志中。在系统启动mount这个文件系统时,只需replay日志,就可将所有的元数据都加载到内存中。BluesFS的数据和日志文件都通过块设备保存到裸设备上(BlueFS和BlueStore可以共享裸设备,也可以分别指定不同的设备)。
 
 bluestore不使用本地文件系统,直接接管裸设备,并且只使用一个原始分区,HDD/SSD所在的物理块设备实现在用户态下使用linux aio直接对裸设备进行I/O操作。由于操作系统支持的aio操作只支持directIO,所以对BlockDevice的写操作直接写入磁盘,并且需要按照page对齐。其内部有一个aio_thread 线程,用来检查aio是否完成。其完成后,通过回调函数aio_callback 通知调用方。

缓存模块

Bluestore实现了自己的缓存机制,定义了structure :OnodeSpace,用来map 到内存中的ONODE;BufferSpace,用来map 块信息blob,每个blob都在bufferSpace中缓存了状态数据。二者在缓存中依照LRU的方式决定生命周期。 

FreelistManager模块

FreelistManager用来映射磁盘的使用信息,最初实现是采用k-v的方式来存储对应的磁盘块的使用情况,但是由于更新数据时需要修改映射,需要线程锁来控制修改,而且这种方式对内存消耗很大;后续修改为bitmap的映射方式,设定一个offset来以bitmap的方式map多个block使用信息,使用XOR计算来更新块的使用情况,这种方式不会出现in-memory 状态。 

Allocator模块 

用来委派具体哪个实际存储块用来存储当前的object数据;同样采用bitmap的方式来实现allocator,同时采用层级索引来存储多种状态,这种方式对内存的消耗相对较小,平均1TB磁盘需要大概35M左右的ram空间
 

bluestore元数据

在之前的存储引擎filestore里,对象的表现形式是对应到文件系统里的文件,默认4MB大小的文件,但是在bluestore里,已经没有传统的文件系统,而是自己管理裸盘,因此需要有元数据来管理对象,对应的就是Onode,Onode是常驻内存的数据结构,持久化的时候会以kv的形式存到rocksdb里。
 
在onode里又分为lextent,表示逻辑的数据块,用一个map来记录,一个onode里会存在多个lextent,lextent通过blob的id对应到blob(bluestore_blob_t ),blob里通过pextent对应到实际物理盘上的区域(pextent里就是offset和length来定位物理盘的位置区域)。一个onode里的多个lextent可能在同一个blob里,而一个blob也可能对应到多个pextent。
另外还有Bnode这个元数据,它是用来表示多个object可能共享extent,目前在做了快照后写I/O触发的cow进行clone的时候会用到。
 

I/O读写映射逻辑

写I/O处理

到达bluestore的I/O的offset和length都是对象内(onode)的,offset是相对于这个对象起始位置的偏移,在_do_write里首先就会根据最小分配单位min_alloc_size进行判断,从而将I/O分为对齐和非对齐的。当一个写请求按照min_alloc_size进行拆分后,就会分为对齐写,对应到do_write_big,非对齐写(即落到某一个min_alloc_size区间的写I/O(对应到do_write_small)。
  • do_write_big
对齐到min_alloc_size的写请求处理起来比较简单,有可能是多个min_alloc_size的大小,在处理时会根据实际大小新生成lextent和blob,这个lextent跨越的区域是min_alloc_size的整数倍,如果这段区间是之前写过的,会将之前的lextent记录下来便于后续的空间回收。
  • do_write_small
在处理落到某个min_alloc_size区间的写请求时,会首先根据offset去查找有没有可以复用的blob,因为最小分配单元是min_alloc_size,默认64KB,如果一个4KB的写I/O就只会用到blob的一部分,blob里剩余的还能放其他的。

读I/O的处理

读I/O请求的处理时也是通过寻找相关联的lextent,可能会存在空洞的情况,即读到未写过的数据,这部分就直接补零。
 

总结

从BlueStore 的设计和实现上看,可以将其理解为用户态下的一个文件系统,同时使用RocksDB来实现BlueStore所有元数据的管理,简化实现。
 
​对于整块数据的写入,数据直接以aio的方式写入磁盘,再更新RocksDB中数据对象的元数据,避免了filestore的先写日志,后apply到实际磁盘的两次写盘。同时避免了日志元数据的冗余存储占用,因为传统文件系统有他们自己内部的日志和元数据管理机制。
 
​对于随机IO,直接WAL的形式,写入RocksDB 高性能的KV存储中。
 
 

--------------------- 本文来自 OshynSong 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/u010487568/article/details/79572390?utm_source=copy 

 

 

bluestore 分区:
block.wal:用于BlueStore的内部日志或写前日志 ssd
block.db:用于存储BlueStore的内部元数据,基于RocksDB实现,类似索引提高性能 ssd
根分区:1.一个小的分区使用XFS进行格式化,并包含OSD的基本元数据。这个数据目录包含关于OSD的信息(它的标识符,它属于哪个集群,以及它的私有密匙环)。
2.设备的其余部分通常是一个大的分区,它占用了由BlueStore直接管理的设备的其余部分,其中包含所有实际的数据。
顺序:wal>db>根
配置:
bluestore_cache_size 每个OSD为BlueStore的缓存所消耗的内存总量 默认为0 如果设置为0 ,hdd和ssd被使用
bluestore_cache_size_ssd ssd占用内存量 默认1gb
bluestore_cache_size_hdd hdd占用内存量 默认3gb
bluestore_cache_meta_ratio bluestore metadate缓存比率 默认0.01
bluestore_cache_kv_ratio kv metadata缓存比率 默认0.99
bluestore_cache_kv_max kv metadata占用最大内存量 默认512 MB
用于数据的缓存的比例是1.0减去元数据和kv比率
校验
bluestore_csum_type 校验类型 默认为crc32c,适合于大多数用途。可选项为none, crc32c, crc32c_16, crc32c_8, xxhash32, xxhash64
用法:ceph osd pool set <pool-name> csum_type <algorithm>
选择crc32c_16或crc32c_8作为校验和算法,可以使用较小的校验和值
内部压缩
BlueStore使用snappy、zlib或lz4支持内联压缩。lz4压缩插件没有在正式版本中发布。
mode:
none:没有压缩数据。
passive:不要压缩数据,除非写入操作是可压缩的提示集。
aggressive:压缩数据,除非写入操作是不可压缩的提示集。
force:无论如何都要压缩数据。
不管模式如何,如果数据块的大小没有足够的减少,它就不会被使用,原始的(未压缩的)数据将被存储。例如,如果bluestore压缩所需的比率被设置为.7 那么压缩后的数据必须是原始数据的70%(或更小)
用法:
ceph osd pool set <pool-name> compression_algorithm <algorithm> 压缩算法ceph osd pool set <pool-name> compression_mode <mode> 压缩模式ceph osd pool set <pool-name> compression_required_ratio <ratio> 压缩比率ceph osd pool set <pool-name> compression_min_blob_size <size> 最小blob大小ceph osd pool set <pool-name> compression_max_blob_size <size>最大blob大小
配置(当单独设置时按osd的定制设置为准):
bluestore compression algorithm lz4, snappy, zlib, zstd 默认snappy bluestore不推荐zstd 
bluestore compression mode none, passive, aggressive, force 默认none
bluestore compression required ratio 默认0.875
bluestore compression min blob size 小于它的块不会被压缩 默认0
bluestore compression min blob size hdd 默认128k
bluestore compression min blob size ssd 默认8k
bluestore compression max blob size 大于它的块在压缩前会被拆成更小的块 默认0
bluestore compression max blob size hdd 默认512k
bluestore compression max blob size ssd 默认64k
spdk用法:
如果采用支持vnme协议的ssd,需要配置 bluestore_block_path.
用法:
lspci -vvv -d 8086:0953 | grep "Device Serial Number"
bluestore block path = spdk:...
---------------------
作者:Law37
来源:CSDN
原文:https://blog.csdn.net/qq_30339341/article/details/78812687
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2018-10-06 16:36  fengjian1585  阅读(1960)  评论(0编辑  收藏  举报