ceph bluestore摒弃了传统的本地文件系统,而直接使用裸磁盘作为OSD的存储介质,因而需要自行管理磁盘空间的分配与回收

概述

一个设计良好的磁盘空间管理器,需要兼顾空间和时间效率;bluestore中提供了空间管理器FreelistManager来支持空间管理,当前提供了一种基于位图的实现,包含:位图持久化以及内存分配器Allocator两部分。其中,位图的持久化是指将空间分配(置1)和回收(置0)的位图状态持久化到磁盘中,基于rocksdb实现;内存分配器是磁盘位图的一致性视图,用来加速空间分配的速度,基于不同的内存组织形式,包括:stupidbitmap, avlhybrid四种。

位图持久化

bluestore中,当前基于bitmap来实现磁盘空间的分配管理,并将位图持久化到rocksdb中,如下图:

从下往上看:下层是磁盘,在逻辑上划分为多个固定大小的block(参数为:bdev_block_size, 默认为4KB);上面是空间管理器,最小分配单位为alloc-block(参数为:bluestore_min_alloc_size),需要为block的整数倍,在SSD磁盘上,默认是4KB,在HDD磁盘上,默认是64KB;一个key管理若干个alloc-block,其value记录这些alloc-block的位图状态(参数为:bluestore_freelist_blocks_per_key,默认为128) 。

举个例子,默认情况下:1TB的SSD磁盘, 包含的block数为:1TB/4KB = 256MB个,包含的alloc-block数为:1TB/4KB = 256MB个,包含的rocksdb的key数为:256MB/128 = 2MB个。

至于SSD和HDD采用不同的分配单位,与他们的物理特性有关:HDD由于自身的机械特性原因,在随机IO中性能比较差,所以bluestore会较大的分配块,然后会尝试将多个IO写到相同的块中,以减少随机io,提升性能;而SSD由于特殊的内部结构,随机性能不受类似HDD的机械特性影响,相反为减少写放大,带来空间浪费,应采用较小的块。

bluestore根据请求的<offset, len>以及bluestore_freelist_blocks_per_key,计算需要置位哪些key上的哪些bit,然后通过事务持久化到rocksdb中。

分配器

bluestore实现了4中分配器,他们在性能,空间占用以及性能稳定性上都有所不同,最开始默认使用stupid,然后默认bitmap,最新的版本默认采用hybrid

stupid分配器

这是最早采用的分配器,其原理是:维持最多10棵二叉树(基于google的C++ btree_map实现,参考:https://code.google.com/archive/p/cpp-btree/),每个节点记录<offset,length>的空闲空间,

  1. 构建树时根据请求的length计算相应的空闲区间应该添加到哪棵树【每棵树所在的位置称为bin,计算方式为:bin = MIN(64 - length所在block的二进制表示的前置0的个数, 9),length所在的block = length/bdev_block_size, 9是最大的bin号,因为一共10棵树】,保证将大块的连续空间放在前面的树中,相近大小的块放在相同或者临近的树上,并对连续的块进行合并。
  2. 分配空间时根据请求的length选择一棵树,首先从这棵树开始往后循环的查找,直到找到合适的区间, 或者没有空间则从这棵树后面的树继续循环的查找,直到找到合适的空间或者没有空间报错,找到空间后将该区间从树中删除,如果存在部分分配还需要将剩余的空闲空间重新加入到合适的树中(查找优化:搜索每棵树时,下界为:第一个节点,上界:根据前一次查找的offset+length值来确定查找区间的下界,减小查找区间的范围)。

从上面的分析,我们可以知道:对于新的OSD,连续空闲空间都较大,空闲块都记录在前面的树中;而随着空间的不断分配使用,一块大的空闲空间被切割为更多小的,不连续的空闲空间,空闲块将打散记录到不同的树中,甚至可能集中记录到末尾的几棵树中;所以,整个森林的内存空间占用不稳定,查找速度不稳定,碎片较严重。

bitmap分配器

这是Mimic版本中的默认分配器,其原理是:通过三层位图来管理整个空闲空间,并充分利用x86架构中的缓存行特性,

  1. 初始化的时候根据磁盘大小,最小分配大小以及内建的常量值,生成一个3层的位图空间,全部置位为0,如下:

    从下往上看:最底层的磁盘,逻辑上划分为若干块,默认块大小为4KB;往上一层是L0,根据最小分配单元将磁盘划分为多个逻辑单元,每64个为一组,由一个slot来管理【每个slot管理64个alloc】,全部的slot组成一个数组。再上一层是L1,以“L0中分配单元的512倍”为分配单元将磁盘划分为多个逻辑单元,每32个为一组,由slot来管理【L1中每个slot管理256个L0层的slot,每个l1-alloc包含8个L0层的slot(称为一个slotset),即每个l1-alloc包含512个L0层的alloc】,全部的slot组成一个数组。最上面一层是L2,以“L1中分配单位的256倍”为分配单元将磁盘划分为多个逻辑单元,每64个为一组,由slot来管理【L2中每个slot管理512个L1层的slot,每个l2-alloc包含8个L1层的slot(称为一个slotset),即每个l2-alloc包含256个L1层的l1-alloc】,全部的slot组成一个数组。
    举个例子,假设有个1TB SSD组成的OSD,配置的bluestore_min_alloc_size=4KB,那么,L0中 alloc=4KB,每个slot管理64个alloc,共4KB64 = 256KB,slot总数为:1TB / 256KB = 4MB个;L1中l1-alloc = 4KB512 = 2MB,每个slot管理32个l1-alloc,共 2MB32 = 64MB,slot总数为:1TB / 64MB = 16KB个;L2中l2-alloc = 2MB256 = 512MB,每个slot管理64个l2-alloc,共512MB*64 = 32GB,slot总数为:1TB / 32GB = 32个。
  2. 构建位图的时候,根据<offset, length>,从L0->L2设置各层的位图,L0和L2层的设置相对简单:根据offset, length,以及alloc计算slot以及slot bit,然后置位即可,用1bit表示一个alloc;L1层的设置相对复杂,需要根据其L0层slot置位状态,如:是全设置?是全空闲?是部分设置?来处理slot以及slot bit部分设置的情况,因为L1层每个alloc/slot管理的区间包含L0层多个alloc/slot管理的区间,结合上图说明:看蓝色区域,l1-alloc包含L0层的8个slot,每个slot包含64个alloc,如果所有的8个slot都是空闲状态(每个bit都为1),那么L1层中的空闲块数加1;如果8个slot中有部分空闲有部分被使用(部分bit为1部分bit为0),那么L1层中的“部分块数”加1;然后根据上面的判断设置L1中slot bit的状态【空闲设置为11,部分占用设置为01,全占用为00,L1中使用2个bit来表示每个l1-alloc,所以每个slot占用64bit
  3. 分配空间的时候, 从L2->L0递归查找可用的空间,首先从L2层找到可用的slot和slot bit,接着根据与L1层的映射关系,得到L1层的起始和结束slotset,然后通过判断每个slot的状态来做进一步的处理:1)对于已使用的slot直接跳过,2)对于空闲的slot则根据与L0层的映射关系,得到L0层的起始和结束slotset,3)对于部分空闲的slot,需要先找到第一个空闲slot bit,然后根据偏移以及与L0层的映射关系,得到L0层的起始和结束slotset,在L0层则根据length以及每个slot/slot bit来设置位图,最后回溯设置L1和L2层的位图,并更新可用空间【过程中位图的映射变更过程:L2的slot/slot bit -> L1的slotset / slot -> L0的slotset /slot / alloc】。

从上面的分析,我们可以知道:bitmap空间初始化即预分配,整体上空间占用上比stupid要大,分配空间时从L2层的第一个空闲slot开始查找,因为L2层(往下层逐级减小)每个slot的空间非常的大,在大部分场景下,分配速度会比较稳定,长尾IO问题得到缓解,整体上性能表现要优于stupid方式,这也是后面以bitmap为默认分配器的原因。【在bitmap的分组设置中,利用了CPU Cache Line的特性,可以加速位图操作 - L1和L0层的slotset 都是512bit(64Byte),这是典型的缓存行大小,CPU从主存读取变量数据时,以Cache Line为单位整体读取 - 类似预读,空间局部性原理; 可以通过命令查看系统缓存行:more /sys/devices/system/cpu/cpu1/cache/index0/coherency_line_size】

AVL分配器

AVL树即平衡二叉树,如果是非空树,左右子树的高度差不超过1。在ceph的空间分配器中定义了两颗avl树:1)根据offset排序的avl树,基于boost的avl_set结构实现,后文称为Tree1,2)根据length排序的avl树, 基于boost的avl_multiset结构实现, 后续称为Tree2。分配空间时优先使用第一棵树,

  1. 在初始化树时,根据<offset, length>中的offset在Tree1中查找插入位置(返回插入的后一个迭代器),并将区间插入到两颗树中,当然还需要注意处理与树中前后节点的合并问题:1)不与前后节点合并,直接插入Tree1和Tree2中, 2)与前或后节点连续,对于Tree1之间更新前后节点的end或start,对于Tree2需要删除前或后节点,插入新的节点,3) 与前后节点均连续,对于Tree1是将前节点合并到后节点,然后执行旋转再平衡,删除前节点,对于Tree2需要删除前和后节点,插入新的节点。
  2. 分配空间时,首先根据length以及Tree2中的最后一个节点的大小(最大的连续区间)来决定从哪棵树中开始查找,如果Tree2中的最大连续块比待分配的length小或者剩余空闲空间小于某个比例(默认4%)或者最大连续块小于某个值(默认128KB),那么就从Tree2分配,否则从Tree1分配【我是这么想的:如果Tree2中的最大连续块比较小或者剩余空间比较少,说明当前的空间已经比较离散,碎片比较多,那么从基于按块大小排序的Tree2分配效率会更高】:查找过程比较简单,就是遍历树,具体实现中有个小的优化:设置一个游标数组,每次分配请求后会记录该次请求命中节点的偏移并记录到游标中,再次收到相同大小的分配请求时,会先从游标中记录的偏移往后遍历树,如果没有找到再从头遍历树;空间分配后,需要从Tree1和Tree2中删除已分配的空间,这里需要处理剩余空间的再插入问题:先从Tree2中得到上述以分配节点的迭代器,然后从Tree2中移除节点,1)如果没有剩余空间,Tree1执行旋转平衡并删除节点,2)如果头部或尾部有剩余,更新节点的start和end信息,重新插入Tree2中,3)如果头部和尾部都有剩余,创建新的尾部节点(后半部分),并插入到Tree1中当前节点的后一个节点的前面以及插入到Tree2中,更新当前迭代器的end信息(前半部分),重新插入Tree2中。

从上面的分析,我们可以知道:对于新的OSD,连续空闲空间都较大,所需要的节点(空间)较少;而随着空间的不断分配使用,一块大的空闲空间被切割为更多小的,不连续的空闲空间,需要更多的节点(空间)来记录整个磁盘空间的分配情况,整棵树内存空间占用不稳定,为优化大量碎片以及低容量情况下分配效率,采用两棵树来记录磁盘空间,所需要的内存在量级上是stupid的两倍, avl tree相比btree更稳定,性能表现会更稳定些。

Hybrid分配器

它是bitmap分配器和avl分配器的组合体,基本思路是:限制avl中的节点个数。

  1. 初始化时,根据上一节avl分配器中介绍的方法初始化树,如果节点个数超过限制【我理解:是碎片比较多了】,就启用bitmap分配器,根据上一节bitmap分配器中介绍的方法初始化树,将新的区间插入到bitmap中。
  2. 分配空间时,如果满足下列条件优先从bitmap中分配:1)bitmap已初始化同时有还有足够的空闲空间,2)待分配的空间很小,小于avl中Tree2的最小块, bitmap的分配方式请查阅上文;否则从avl中分配,avl的分配方式请查阅上文。

从上面的分析,我们可以知道:这个分配器是大块的分配用avl,充分发挥avl(小)树的性能优势,尽量避免碎片化;小块分配用bitmap,发挥bitmap在小块分配上的性能优势以及稳定性。

总体上,bitmap应该是最稳定的分配器,而如果对业务的工作负载以及io模型非常清楚,可以考虑用hybrid。

ceph bluestore中的磁盘空间管理相关推荐

  1. Doris之磁盘空间管理(重点)

    Doris之磁盘空间管理(重点) 磁盘存储空间有关的系统参数和处理策略. Doris 的数据磁盘空间如果不加以控制,会因磁盘写满而导致进程挂掉.因此我们监测磁盘的使用率和剩余空间,通过设置不同的警戒水 ...

  2. Jenkins服务器磁盘空间管理策略

    Jenkins在帮助我们自动化构建服务的同时也在消耗服务器的磁盘空间,试想如果构建的项目个数很多,而Jenkins 服务器磁盘空间又不是非常大的话,每隔一段时间磁盘空间就会爆满导致Jenkins出现磁 ...

  3. 查找磁盘占用最大的文件linux,linux查找系统中占用磁盘空间最大的文件

    Q:下午有一客户磁盘空间占用很大,使用df查看磁盘剩余空间很小了,客户想知道是哪些文件占满了文件. Q1:在Linux下如何查看系统占用磁盘空间最大的文件? Q2:在Linux下如何让文件夹下的文件让 ...

  4. 操作系统 第7 ,8 章 文件与磁盘空间管理

    第7 ,8 章 文件与磁盘空间管理 1.文件和文件系统 文件管理:把所管理的程序和数据组织成一系列的文件,并能进行合理的存储.使用等操作. 1 )基本概念 数据项:描述对象某种属性的字符集:是数据组织 ...

  5. 简单好用的树莓派磁盘空间管理工具

    简单好用的树莓派磁盘空间管理工具 问题来源:树莓派系统备份时全盘备份太浪费空间,而众所周知,windows下是很难对linux定义的磁盘做修改的,在网上冲浪了一会,总结了一个比较方便的方法. 解决办法 ...

  6. 文件管理 磁盘空间管理

    目录 https://blog.csdn.net/weixin_45792450/article/details/109314765 磁盘空间管理意义 文件信息在大部分时间内都是存放在外存储器(主要是 ...

  7. 磁盘空间管理工具FolderSizes

    现在的硬盘已经到了用TB来计量的级别,但也会感觉在不知不觉间空间竟然不够用了!到底什么东西占用了我们这么多的磁盘空间呢? 这个软件可以帮你快速进行分析. FolderSizes 企业版是一款优秀的磁盘 ...

  8. 系统盘压缩卷小于可用空间_操作系统中的可用空间管理

    系统盘压缩卷小于可用空间 可用空间管理 (Free space management) As we know that the memory space in the disk is limited. ...

  9. 正版软件 | DaisyDisk:Mac 电脑一流的磁盘空间管理工具

    使用 Mac 工作时,平时创建并下载大量文件,但很容易忘记或者很少删除这些内容.但是有一天,您发现启动磁盘已红,但是自己又好似没有安装啥软件,这时候就会想到底是哪些数据占用了这么大的空间?! 作为一名 ...

最新文章

  1. 【Linux】类Unix 操作系统进程监控控制工具 Supervisor
  2. Android中的Fragment
  3. 【机器翻译】transformer
  4. ubuntu16.04 下安装配置python3.6
  5. 【开源】Tsar——灵活的系统和应用采集软件
  6. opera for android,Opera Mobile浏览器
  7. Oracle数据库中scott用户不存在的解决方法
  8. Leetcode431.将N叉树编码为二叉树(golang)
  9. 破解网站发布系统 ASP生成静态页面方法
  10. RecycleView的普通适配器(另加RecycleView的格局格式)
  11. python 时分秒相加大于24h_在python中,将24小时加到负时间差上
  12. cad打印本计算机未配置,CAD打印的基本设置详细教程
  13. 开发QQ桌球瞄准器(5):使用注册表保存配置
  14. iOS图片加载策略的简单实现
  15. 跨境公路货运调研分析-市场规模、市场份额、市场定位、产品类型以及发展规划
  16. 微信开挂怎么防止封号_再也不怕被封号!微信养号秘笈教你防封号防降权
  17. 【cocos2D-X】Plist使用 实现 移动精灵多图片动画
  18. Altium Designer 18PCBLogo制作
  19. linux6.5取消屏保,怎么把wps屏保关掉
  20. 数据挖掘的十大经典算法

热门文章

  1. WiFi无线网络参数 802.11a/b/g/n 详解
  2. openCV: 利用python和cv2绘出一个笑脸
  3. 聚焦“芯”产业,搭建“芯”桥梁——清微智能出席AIIA2020年度AI芯片交流会
  4. 关于assert函数的调用警告:implicit declaration of function 'ASSERT' is invalid in C99
  5. JVM-内存与垃圾回收篇!女朋友看了都想当架构师的超详细保姆级笔记!呕心沥血之作!看完还不会你砍我!
  6. 密码应用安全性评估实施要点之二密码技术应用要求与实现要点(4)
  7. k-近邻算法 From Machine Learning
  8. Visio2016中图标的查找
  9. EXCEL破冰 - 锁定单元格样式和输入格式
  10. FI---SAP汇率损益处理方法