首页 > ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析

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

文章目录

        • 内存查看
        • 内存控制
        • 内存控制源码分析
          • 通过gperftools接口获取osd进程实际内存 动态设置cache大小
          • 动态调整cache比例
          • trim释放内存


本文通过对ceph-osd内存查看跟踪的5种手段以及osd内存控制的方式进行源码层面的说明,并未通过修改相关源码进行控制(水平不够),仅限于使用社区已开发好的参数进行相关配置的跟进而已,如想要追求更加精确的理解,可以对 osd/bluestore/rocksdb相关源码实现进行阅读

ceph版本 12.2.1 - 12.2.12

内存查看

  1. 最常用的内存初始查看方法top -u ceph |grep ceph-osd,通过交互式输入c,2次e即可看到如下效果。其中单个osd进程占用内存为res

    在这里插入图片描述

  2. ceph tell osd.0 heap stats

    这种方式主要查看osd运行过程中占用的内存:

    第一项: Bytes in use by application 包括bluestore cache,rocksdb_cache,bluefs,pglog等数据信息

    第二项:Bytes in page heap freelist 内存页堆管理的空闲空间链表

    第三项:Bytes in central cache freelist中心缓冲区占用

    第四项:Bytes in transfer cache freelist 交换缓冲区占用

    第五项:Bytes in thread cache freelists 线程缓冲区占用

    第六项:Bytes in malloc metadata malloc为元数据分配的空间

    ceph是使用tcmalloc 空间分配器进行空间分配,其中由tcmalloc分配的但是并未被ceph进程使用的空间可以通过

    ceph tell osd.id heap release

    在这里插入图片描述

  3. google-perftools工具实时跟踪osd/mon进程内存占用,精确到具体的函数。关于pprof的安装以及如何使用其来查看osd内存占用,可以参考pprof搭配ceph tell命令分析ceph内存

    效果如下:

    (pprof) top10
    Total: 2525 samples
    298  11.8%  11.8%	 345  13.7% runtime.mapaccess1_fast64
    268  10.6%  22.4%	2124  84.1% main.FindLoops
    251   9.9%  32.4%	 451  17.9% scanblock
    178   7.0%  39.4%	 351  13.9% hash_insert
    131   5.2%  44.6%	 158   6.3% sweepspan
    119   4.7%  49.3%	 350  13.9% main.DFS96   3.8%  53.1%	  98   3.9% flushptrbuf95   3.8%  56.9%	  95   3.8% runtime.aeshash6495   3.8%  60.6%	 101   4.0% runtime.settype_flush88   3.5%  64.1%	 988  39.1% runtime.mallocgc...
    

    各个参数含义如下:

    • The first column contains the direct memory use in MB. 函数本身使用的内存

    • The fourth column contains memory use by the procedure and all of its callees.函数本身内存+调用函数内存

    • The second and fifth columns are just percentage representations of the numbers in the first and fourth columns. 第二第五列分别为第一列,第四列与total的比值

    • The third column is a cumulative sum of the second column.第三列为(到当前行数为止)第二列所有的和

    注意:该命令需要heap start_profiler长期运行才能够利用pprof抓取更多有效信息。

  4. ceph原生命令,由ceph内存池(bstore线程)管理的内存各项数据占用,可以通过调整mempool_debug = true参数来查看详细打印

    ceph daemon osd.16 dump_mempools

    打印信息如下:

    这里能够看到内存池中各个数据结构的items个数和bytes总空间大小,关于当前命令如何动态获取各个数据结构的内容相关得源码分析可以参考admin_socket实时获取内存池数据 文章

    在这里插入图片描述

  5. valgrind搭配massif,查看进程内存占用,能够看到内存分配栈并且精确到具体的函数;详细的配置以及更加高级全面的内存查看方法可以参考valgrind搭配massif、vgdb分析ceph-mon内存

    linux端的mon进程占用效果查看如下:

    在这里插入图片描述

    最下侧即为进程内存占用栈,并且在运行时间点上提供快照以及峰值的内存占用情况,能够很清晰得看到各个时间点内存如何上涨上来,同时massif提供可视化的图形页面(火焰图)来查看进程内存:

    在这里插入图片描述

内存控制

本文的内存控制版本基于ceph 12.2.12版本,相关的参数描述同样是基于12.2.12版本,当前12.2.12ceph版本真正实现了osd进程内存的精准控制

bluestore相关参数说明

bluestore_min_alloc_size_hdd = 65536  #hdd做osd时的bluestore 分配空间的最小粒度 64K
bluestore_min_alloc_size_ssd = 16384  #ssd做osd时bluestore分配空间的最小粒度 16K
bluestore_cache_size_hdd = 1073741824 #hdd做osd时的bluestore_cache的大小,1G,该参数主要用于缓存元数据,键值数据以及部分data数据
bluestore_cache_size_ssd = 3221225472 #ssd做osd时的bluestore_cache的大小,默认3G
bluestore_cache_trim_interval = 0.05  #bluestore cache 裁剪的时间间隔,每隔0.05秒会尝试对不使用的cache种的数据(onode,blob,extents)释放
bluestore_cache_trim_max_skip_pinned = 64 #每次trim时的onode的个数

osd内存相关控制参数

osd_memory_base = 805306368 #osd内存占用的最小值,默认768M
osd_memory_target = 838860800 # 真正限制osd内存的上限,即我们top 种看到的进程实际内存占用会维持在当前参数设置的值以下。这里我们设置的800M
osd_memory_cache_min = 134217728 #osd 内存 cache占用的最小值,128M
osd_memory_cache_resize_interval = 1.0 #osd cache大小的实际调整的时间间隔,每隔1秒,进行一次cache大小的调整
bluestore_cache_autotune_interval = 5 #osd每隔5秒调整一次bluestore cache的比例
bluestore_cache_autotune_chunk_size = 33554432 #osd每次调整 bluestore cache的最小单位,32M
bluestore_cache_kv_ratio = 0.4 #bluestore cache 存储键值cache的比例
bluestore_cache_meta_ratio = 0.4 #bluestore cache 存储元数据cache的比例

内存控制源码分析

主要内存控制方式是通过在osd_memory_cache_resize_interval时间间隔内获取osd进程的实际内存,判断其是否超过设定的osd_memory_target的数值,并进行cache大小的调整,最终通过trim释放内存。

关键地实现难点为以下几个地方:

  • 获取osd进程的实际内存
  • 动态调整cache比例
  • 动态设置cache大小
  • trim释放内存
通过gperftools接口获取osd进程实际内存 动态设置cache大小

因为ceph内存分配使用的tcmalloc进行的,ceph这里是通过gperftools提供的获取tcmalloc内存分配的接口进行获取

src/os/bluestore/BlueStore.cc 在bstore的线程函数种void *BlueStore::MempoolThread::entry()

在这里插入图片描述

通过_tune_cache_size调用gperttools提供的tcmalloc获取内存分配的接口获取内存大小

在这里插入图片描述

在这里插入图片描述

将最终需要调整的cache大小已全局变量auto_tune_size返回

关于gperftools获取已占有内存的接口实现可以github下载gperftools-master源码https://github.com/gperftools/gperftools,这里仅贴出将未使用内存页但以申请的内存页释放回操作系统的代码调用,其他获取总的内存页接口和未使用内存页接口详细实现有兴趣的同学可以去看看:

void ceph_heap_release_free_memory()
{ MallocExtension::instance()->ReleaseFreeMemory();
}void MallocExtension::ReleaseFreeMemory() { ReleaseToSystem(static_cast<size_t>(-1));   // SIZE_T_MAX
}virtual void ReleaseToSystem(size_t num_bytes) { SpinLockHolder h(Static::pageheap_lock());if (num_bytes <= extra_bytes_released_) { // We released too much on a prior call, so don't release any// more this time.extra_bytes_released_ = extra_bytes_released_ - num_bytes;return;}num_bytes = num_bytes - extra_bytes_released_;// num_bytes might be less than one page.  If we pass zero to// ReleaseAtLeastNPages, it won't do anything, so we release a whole// page now and let extra_bytes_released_ smooth it out over time.Length num_pages = max<Length>(num_bytes >> kPageShift, 1);size_t bytes_released = Static::pageheap()->ReleaseAtLeastNPages(num_pages) << kPageShift;if (bytes_released > num_bytes) { extra_bytes_released_ = bytes_released - num_bytes;} else { // The PageHeap wasn't able to release num_bytes.  Don't try to// compensate with a big release next time.  Specifically,// ReleaseFreeMemory() calls ReleaseToSystem(LONG_MAX).extra_bytes_released_ = 0;}}
动态调整cache比例

关于bluestore cache的作用,很明显,将高命中的脏数据(kv数据,元数据)等数据放入到缓存种,加速bluestore io读写能力。

其中bluestore cache维护了一个cache优先级列表如下

在这里插入图片描述

最高优先级为kv cache,其次 meta cache,最后剩余的提供给data cache。

优先级越高的cache,分配内存资源,调整内存资源优先分配。当然占用的大小则是由我们以上图的两个ratio参数进行控制。

  • 初始化cache,设置优先级cache内存占用的比例
    _adjust_cache_settings();
    void BlueStore::MempoolThread::_adjust_cache_settings()
    { store->db->set_cache_ratio(store->cache_kv_ratio);meta_cache.set_cache_ratio(store->cache_meta_ratio);data_cache.set_cache_ratio(store->cache_data_ratio);
    }
    
  • 动态调整 cache

    在这里插入图片描述

    从动态设置cache大小中tune_cache_size获取到的可以分配的cache大小auto_tune_cache_size,将其根据各个cache的ratio比例分配给优先级cache
    void BlueStore::MempoolThread::_balance_cache(
    const std::list<PriorityCache::PriCache *>& caches)
    { //初始值为osd内存最小值 osd_memory_cache_min 128M,该值在tune_cache_size种动态调整int64_t mem_avail = autotune_cache_size;//根据对应cache的优先级进行cache容量的分配// Assign memory for each priority levelfor (int i = 0; i < PriorityCache::Priority::LAST + 1; i++) { ldout(store->cct, 10) << __func__ << " assigning cache bytes for PRI: " << i << dendl;PriorityCache::Priority pri = static_cast<PriorityCache::Priority>(i);_balance_cache_pri(&mem_avail, caches, pri);}//将剩余的未分配的cache 按照比例再重新分配// Assign any leftover memory based on the default ratios.if (mem_avail > 0) { for (auto it = caches.begin(); it != caches.end(); it++) { int64_t fair_share =static_cast<int64_t>((*it)->get_cache_ratio() * mem_avail);if (fair_share > 0) { (*it)->add_cache_bytes(PriorityCache::Priority::LAST, fair_share);}}}// assert if we assigned more memory than is available.assert(mem_avail >= 0);// Finally commit the new cache sizesfor (auto it = caches.begin(); it != caches.end(); it++) { (*it)->commit_cache_size();}
    }
    
    针对每个优先级Cache的大小调整则遵循如下规则:
    1. 获取优先级cache想要的容量,通过bluestore_cache_autotune_chunk_size 34M单位进行分配
    2. 优先级cache 想要的容量大于cache剩余容量,将cache剩余的容量都提供给当前优先级cache
    3. 优先级cache 想要的容量小于cache剩余容量,直到分配足够

      在这里插入图片描述
trim释放内存

每隔bluestore_cache_trim_interval会尝试释放一次内存,每次尝试释放元数据的个数为bluestore_cache_trim_max_skip_pinned,释放内存后当osd总内存超过osd_memory_target,则不再进行cache相关的大小调整;否则仍然继续将未超过的部分应用于cache分配。



计算好需要trim的元数据个数和缓存大小,调用对应的cache trim函数。

在这里插入图片描述

bluestore默认使用的是淘汰算法更优的TwoQCache,则调用对应的void BlueStore::TwoQCache::_trim(uint64_t onode_max, uint64_t buffer_max)执行内存释放即可。

关于内存控制,osd_memoiry_target及其一系列控制衍生参数尤为关键。ceph在L版本低版本并未做得足够完善,但是L版本的最新版已经将内存控制逻辑完善,总之在保证性能的前提下OSD内存控制更加更加精准。

更多相关:

  • 本文研究nginx提供的缓存功能,下面是实操记录。 这篇博文基于前面文章的基础上搭建,至始至终都是root用户操作 http://blog.csdn.net/tao_627/article/details/78953800 缓存清除功能需要借助第三方模块ngx_cache_purge,其链接如下 https://github...

  • 下面是参考文献[1]的翻译 简介 ATS既可以用作HTTP代理,也可以用作HTTP缓存,ATS能够缓存任何字节流,虽然它当前只支持HTTP协议传输的字节流,当这样的流缓存时,会带一个HTTP协议头部,会命名为缓存中的一个对象object。每个对象通过一个名为cache key的全局唯一值识别。 该文档的目的是描述ATS缓...

  • 对Squid使用的几点总结 1.cache_dir 在Linux环境下用aufs类型的cache_dir比较稳定,速度也比较快。cache_dir所在文件系统如果用noatime选项来mount,可以避 免访问cache文件时经常要更新access time的操作。 一般cache容量和被加速内容的比值...

  • 策略模式作为行为型设计模式中的一种,主要封装相同功能的不同实现算法,用于在用户程序内部灵活切换。对用户来说能够快速替换对应的算法,能够让算法的实现独立于使用的用户。 基本的UML类图如下: 用户使用Stratey的实例能够快速得在不同的Cache算法之间灵活切换(直接使用对应的Cache实例来设置到Strategy之中即可。),...

  • 环境 ceph版本:12.2.1 部署模式:ec 2+1 osd: 3个 且资源池已经有数据 执行命令:ceph daemon osd.0 flush_store_cache 进行刷缓存。即将dump_mempools内存池管理的bluestore cache中的无用数据进行释放 主要参数: bluestore_cache_tr...

  • 更多内容,欢迎关注微信公众号:全菜工程师小辉~前言在笔者上一篇博客,详解了NIO,并总结NIO相比BIO的效率要高的三个原因,彻底搞懂NIO效率高的原理。这篇博客将针对第三个原因,进行更详细的讲解。首先澄清,零拷贝与内存直接映射并不是Java中独有的概念,并且这两个技术并不是等价的。零拷贝零拷贝是指避免在用户态(User-space)...

  • 一、预备知识—程序的内存分配  一个由c/C++编译的程序占用的内存分为以下几个部分  1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈,如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器...

  • 我的爱机是一台ThinkPad T420,原装三星DDR 1333 4G内存一根,还剩一根内存位置,最近趁京东6.18促销,准备增加一根物理内存。为了确保兼容性,觉得仍然选购DDR 1333 4G内存,于是购买了金士顿这款,比如DDR3 1600的还贵。 这个安装过程完全参照该内存的网页提示进行 这里简单记录一下,以备...

  • 陪伴我多年的老本ThinkPad T420渐渐垂垂老矣, 我想更新一下可以更新的部分, 比如将2.5寸HDD更换为SSD, 将单条4G内存再增加一根, 凡此种种想法, 可能最后归结为如何获取该笔记本的硬件配置信息, 在windows下面使用鲁大师之类的检测软件, 也许很好搞定,但是在Ubuntu 14.04平台上如果办到呢? 很简单...

  • 一.内存错误出现的场景 这几天在重构ATS插件代码的过程中遇到了烦人的内存泄露问题, 周五周六连续两天通过走查代码的方法,未能看出明显的导致内存错误的代码, 同时也觉得C和C++混合编程得到一个动态库, 在一个.cpp主文件中,即用new又用malloc来动态分配内存, 可能会导致内存错误.后来网上调研和查资料发现, new和mal...

  • 文章目录1. 解决问题2. 应用场景3. 实现方式C++实现C语言实现4. 缺点5. 和其他三种创建模式的对比(单例,工厂,建造者) 1. 解决问题 如果对象的创建成本较大,而同一个类的不同对象之间的差别不大(大部分字段相同),在这种情况下,我们可以利用已有对象(原型)进行赋值(拷贝)的方式,创建新的对象,从而达到节省对象创...

  • 混合osd的部署 先部署所有的ssd 在/etc/ceph.conf中最后添加ssd做osd的block大小如下: 比如部署中有两个ssd,则添加 [osd.0] bluestore_block_size = xxxx [osd.1] bluestore_block_size = xxx 如上的size大小计算如下,如ssd容量...

  • 文章目录Pool创建ec pool创建副本pool创建Pool参数创建根故障域及添加osd其他命令Tier相关 Pool创建 ec pool创建 创建profile ceph osd erasure-code-profile set $profile_name k=$k m=$m crush-failure-domain...

  • 文章目录简介使用OSD相关操作PG相关操作对象相关操作总结 简介 ceph-objectstore-tool工具,能够操作到ceph最底层的数据,包括pg,对象层级。它能够对底层pg以及对象相关数据进行获取、修改。并能够对一些问题pg和对象进行简单修复。所以使用该工具进行操作的时候需要谨慎(涉及到修改的操作最好备份一份数据)...

  • 文章目录ceph版本:环境配置:异常问题:问题解决:总结 ceph版本: ceph 12.2.1 环境配置: tier_pool 16个分区大小800G 的osd容量 3副本 data_pool 32个4T盘 3副本 异常问题: ps:在分布式存储中遇到任何问题都不要先去通过重设存储节点,清除磁盘数据来解决,一定要...