文章目录

  • 环境
  • 原理说明
  • 总结

环境

ceph:12.2.1
场景:ec 2+1
部署cephfs,执行如右写模式:dd if=/dev/zero of=/xxx/cephfs bs=6K count=4 oflag=direct
关键配置:
bluestore_min_alloc_size_hdd = 65536 bluestore分配空间的最小粒度 单位:B
bdev_block_size = 4096 磁盘分配空间的最小粒度 单位:B

原理说明

以上dd写方式总共直写四次6K大小的io,每一个io在经过PG落到bluestore层次会根据分片大小2副本+1校验块 被拆分为3K大小的 io到每个osd上

  1. 第一次写3K io 由于未chuck(bdev_size 4K )对齐,则对3K io补零后和bdev_size对齐,然后写入bluestore按照bluestore_min_alloc_size_hdd大小分配的blob中


    bluestore.cc :_txc_add_transaction–> _write --> _do_write–>_do_write_data --> _do_write_small
    直接写入一个新的blob中
    _do_alloc_write txc 0x7fcb6e6443c0 1 blobs

  2. 第二次写3K io主要执行如下步骤:
    a. 会先进行clone blob1
    b. 使用前1K 数据补齐blob1中的lextent1,再重新分配一个blob,写入补齐后的lextent3
    c. 剩下的2K io用0补齐后写入新的lextent4
    d. 移除lextent1对临时onode的引用,remove临时onde,进而释放lextent1对blob1的引用,进而释放blob1回收磁盘空间

    a. 执行clone

    这里clone是为当前extent创建一个单独的onode,即一个新的对象 空间来存储,所以这里可以看到offset从0开始分配

    这里在执行clone的时候根据bluestore配置参数bluestore_clone_cow来判断是否执行cow机制:即当前io补齐上一个extent之后,为其重新分配一个blob并写入。RMW:需要有额外的写,即先读出当前blob的extent数据,使用第二次io的前1K补齐改blob,再写入当前blob空间。bluestore为了提升性能,减少小写次数,这里默认使用了cow机制。
    bluestore.cc :_txc_add_transaction–> _clone --> _do_clone

    b. 此时blob1即被两个逻辑段lexten共享,则blob1成为sharedblob
    接下来使用1K数据补齐lextent1的3K,同时使用0补齐当前剩余2K,补齐后的数据如下

c. 将补齐后的第一个4K IO写入到lextent3中,第二次io剩余的数据写入到lextent4中

可以看到这里进行了两次写,第一次是写clone之后补齐的数据,第二次写剩余用0补齐的数据。因为第一次写是重新分配了blob,所以offset 为0,第二次写是紧接着第一次的写,所以这里offset为4096

补齐后的第一次写 ,执行小写,分配了一个新的blob
bluestore.cc :_txc_add_transaction–> _write --> _do_write–>_do_write_data --> _do_write_small

第二次写为直接写入blob中未使用的块
bluestore.cc :_txc_add_transaction–> _write --> _do_write–>_do_write_data --> _do_write_small

写完之后的blob和extent引用关系如下

d. 此时释放lextent1对blob1的引用如下:

垃圾回收,进而释放lextent1
bluestore.cc :_txc_add_transaction–> _write --> _do_write

_txc_add_transaction–> _write --> _do_write --> _wctx_finish
释放blob1中lexten1对blob1的引用

同时remove临时onode(clone后的extent2所在的内存元数据结构),并释放blob1的空间.最终第二个3k io写完效果如下


_txc_add_transaction–> _remove --> _do_remove -->

回收磁盘空间 _txc_add_transaction–> _remove --> _do_remove --> _do_truncate --> _wctx_finish

_txc_add_transaction–> _remove --> _do_remove --> _do_truncate --> _wctx_finish

第三次写 3K io同样会进行一次clone,不过clone完成之后的补齐上一次io的写lextent4和新的补零写lextent5之后blob2成为sharedblob,但是由于shareblob仍然再被lextent3引用,所以此时无法remove blob2

第四次写3k io,同上最后的映射关系如下

源码调用栈如下,本调用栈只打到了_do_write_small这一层,具体如何向源码加入函数调用栈可以参考ceph bluestore源码梳理:C++ 获取线程id:

ceph-osd(BlueStore::_do_write_small(BlueStore::TransContext*,
ceph-osd(BlueStore::_do_write(BlueStore::TransContext*,
ceph-osd(BlueStore::_write(BlueStore::TransContext*,
ceph-osd(BlueStore::_txc_add_transaction(BlueStore::TransContext*,
ceph-osd(BlueStore::queue_transactions(ObjectStore::Sequencer*,
ceph-osd(PrimaryLogPG::queue_transactions(std::vector<ObjectStore::Transaction,
ceph-osd(ECBackend::handle_sub_write(pg_shard_t, boost::intrusive_ptr<OpRequest>,
ceph-osd(ECBackend::_handle_message(boost::intrusive_ptr<OpRequest>)+0x327)
ceph-osd(PGBackend::handle_message(boost::intrusive_ptr<OpRequest>)+0x50)
ceph-osd(PrimaryLogPG::do_request(boost::intrusive_ptr<OpRequest>&,
ceph-osd(OSD::dequeue_op(boost::intrusive_ptr<PG>, boost::intrusive_ptr<OpRequest>,
ceph-osd(PGQueueable::RunVis::operator()(boost::intrusive_ptr<OpRequest> const&)+0x57)
ceph-osd(OSD::ShardedOpWQ::_process(unsigned int, ceph::heartbeat_handle_d*)
ceph-osd(ShardedThreadPool::shardedthreadpool_worker(unsigned int)+0x839)

总结

综上,我们可以看到bluestore在非对齐写4个io时会进行3次clone,总共执行6次do_write_small方式的小写。这里是因为clone时使用了cow机制,然而我们使用RMW时会额外增加一次写。可以参考_clone函数中的逻辑。所以按照如上测试方式,每经过4次io,bluestore会进行9次的小写。这里bluestore为了性能稳定,牺牲磁盘空间来将cow机制作为默认的非对齐写处理方式。

ceph bluestore源码分析:非对齐写逻辑相关推荐

  1. ceph bluestore 源码分析:刷缓存(trim)逻辑

    环境 ceph版本:12.2.1 部署模式:ec 2+1 osd: 3个 且资源池已经有数据 执行命令:ceph daemon osd.0 flush_store_cache 进行刷缓存.即将dump ...

  2. ceph bluestore源码分析:admin_socket实时获取内存池数据

    环境: 版本:ceph 12.2.1 部署完cephfs 使用ceph-fuse挂载,并写入数据 关键参数: debug_mempool = true 将该参数置为true即可查看详细的blustor ...

  3. ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析

    文章目录 内存查看 内存控制 内存控制源码分析 通过gperftools接口获取osd进程实际内存 动态设置cache大小 动态调整cache比例 trim释放内存 本文通过对ceph-osd内存查看 ...

  4. ceph bluestore源码分析:C++ 获取线程id

    阅读ceph源码过程中需要明确当前操作是由哪个线程发出,此时需要根据线程id来确认线程名称 C++获取线程id是通过系统调用来直接获取 函数描述 头文件:<sys/syscall.h> 函 ...

  5. 源码分析系列 | 从零开始写MVC框架

    1. 前言 2. 为什么要自己手写框架 3. 简单MVC框架设计思路 4. 课程目标 5. 编码实战 5.1 配置阶段 web.xml配置 config.properties 自定义注解 5.2 初始 ...

  6. ArrayList源码分析与手写

    本节主要分析JDK提供的ArrayList的源码,以及与自己手写的ArrayList进行对比. ArrayList源码分析 构造方法 private static final int DEFAULT_ ...

  7. Nginx源码分析--数据对齐posix_memalign和memalign函数

    posix_memalign函数() /*  * 背景:  *      1)POSIX 1003.1d  *      2)POSIX 标明了通过malloc( ), calloc( ), 和 re ...

  8. SSM源码分析之Spring11-手写SpringORM

    目录导航 前言 SpringJDBC 异常处理 config 模块 core 模块 JdbcTeamplate RowMapper 元数据 metaData 模块 使用 SqlParameterSou ...

  9. 我的世界java刷怪数量_我的世界Minecraft源码分析(1):刷怪逻辑

    这个系列通过对我的世界Minecraft源码进行拆分讲解,让大家可以清除的了解一款游戏是怎么一步步被实现出来的,下面就介绍Minecraft源码第一篇内容,关于刷怪逻辑. 生成循环 生物大致划分为四种 ...

最新文章

  1. 【字符串操作之】大小写转换→→toLocaleLowerCase、toLocaleUpperCase
  2. sql2012一段时间无法连接报53错误
  3. [阅读笔记]Zhang Y. 3D Information Extraction Based on GPU.2010.
  4. 小米无缝切换60hz/90hz/120hz/144hz刷新率!
  5. java io流不关闭_Java IO流关闭问题的深入研究
  6. Python 从入门到进阶
  7. iOS13:UISceneDelegate
  8. Juniper-SRX-基于域控认证的用户防火墙
  9. c语言编程仓鼠吃豆子,动态规划之仓鼠吃豆子 - osc_8quu62cg的个人空间 - OSCHINA - 中文开源技术交流社区...
  10. 人工智能基础:人工智能云服务(Alaas)介绍
  11. vue-json-editor json编辑器
  12. BPF-JIT中bug归类
  13. Oracle表数据转换为XML格式数据
  14. ASO优化之如何使用 Apple 活动功能及应用内事件 (IAE) 来提高您的自然可见度?
  15. 医院无线认证平台怎么样
  16. 学微服务必经之路——Nacos新手入门(下)
  17. WPF中ListBox怎么双击只是双击里面的项而已,而不把其他空白的区域也双击!
  18. FTP:文件传输协议
  19. 电影主题网站设计——仿360影视网站(1页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设
  20. 地理探测器的应用方法

热门文章

  1. 用C#来开发CAD插件,含源代
  2. Programming C# 学习笔记(二) 出发:“Hello World”
  3. 《OpenCV3编程入门》学习笔记5 Core组件进阶(一)访问图像中的像素
  4. php localcompare,JS中使用sort结合localeCompare实现中文排序实例_javascript技巧
  5. ajax 没有权限 -quot;跨域quot;,如何解决AJAX中跨域访问出现'没有权限'的错误
  6. oracle本地验证,Oracle 本地验证和密码文件
  7. linux 窗口z order,wxPython窗口z-order设置
  8. 晴天计算机按键,电脑怎样才能在按键的时候,按下去按键没反应,手台起来才有呢?...
  9. Linux中锚定符号的作用,Linux基础(9)文本处理三剑客之grep
  10. vscode插件可以直接复制到_一款可以让代码“跳舞”的 VS Code 插件:Power Mode