当前位置: 首页 > 编程日记 > 正文

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内存控制更加更加精准。

相关文章:

c语言函数库学习~sscanf~格式化输入

---恢复内容开始--- 今天算是被打击到了吧&#xff0c;由郑轻的acm老师来我学院指导安排了个现场的小比赛&#xff0c;&#xff0c;俺们居然有还是输给一个大一的新手&#xff0c;&#xff0c;哎&#xff0c;情何以堪&#xff0c;&#xff0c;所以还是要重视下基础编程能力的培…

java mobile phone games_j2me100-src Java

文件名大小更新时间codesc.net\[J2SE]应用编程150例\chap01\实例1\BorderLayoutDemo.class8192003-07-07codesc.net\[J2SE]应用编程150例\chap01\实例1\BorderLayoutDemo.java5752003-07-07codesc.net\[J2SE]应用编程150例\chap01\实例1\BoxLayoutFrame.class7262003-07-15code…

***突然断开可能是ADSL猫惹的祸

在我们使用服务器的时候&#xff0c;最讨厌的就是无故的断线了&#xff0c;可能正在和好一起副本&#xff0c;或者正在视频热聊中&#xff0c;还或者youtube视频看的正起劲&#xff0c;突然windows一个对话框弹出 - “连接已经断开”。实在是太影响体验了&#xff0c;断开之后&…

文件中数组的最大值及其对应的最小下标

2019年春季学期第二周作业基础作业请在第一周作业的基础上&#xff0c;继续完成&#xff1a;找出给定的文件中数组的最大值及其对应的最小下标&#xff08;下标从0开始&#xff09;。并将最大值和对应的最小下标数值写入文件。 输入&#xff1a;请建立以自己英文名字命名的txt文…

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

环境&#xff1a; 版本&#xff1a;ceph 12.2.1 部署完cephfs 使用ceph-fuse挂载&#xff0c;并写入数据 关键参数&#xff1a; debug_mempool true 将该参数置为true即可查看详细的blustore管理的内存池的数据 命令&#xff1a; ceph daemon osd.id dump_mempools该命令为ad…

java clob内存溢出_java - java.sql.SQLException:ORA-01704:字符串文字太长时插入或更新 - 堆栈内存溢出...

通常&#xff0c;当我插入4000个字符限制时&#xff0c;它的工作正常&#xff0c;但当超过4000个字符时&#xff0c;它抛出SQL异常字符串文字太长&#xff0c;即使我的DISCHARGE_TEXT数据类型是CLOB我的JavaScript代码是function saveAsDraftNew(){var admissionNo document.g…

LC并联谐振回路

转载于:https://www.cnblogs.com/prayer521/p/4103091.html

zencart分类页产品页去掉url中的id号

最近公司新上的网站被seo指出要修改url&#xff0c;去掉url中产品id。由于我们用的是zencart框架&#xff0c;装了 Ultimate SEO URLs 插件&#xff0c;所以在网上应该有这方面的资料&#xff0c;本文主要参考资料&#xff1a;原网址&#xff1a;修改seo url中去掉产品id的方法…

hexo博客更新主题后上传Git操作

克隆主题: git clone https://github.com/SuperKieran/TKL.git _config.yml文件中主题改为新增主题 # Extensions ## Plugins: https://hexo.io/plugins/ ## Themes: https://hexo.io/themes/ theme: TKL 进入主题目录,更新git cd theme/TKL git pull 执行更新 hexo clean hex…

ceph bluestore源码分析:非对齐写逻辑

文章目录环境原理说明总结环境 ceph:12.2.1 场景&#xff1a;ec 21 部署cephfs&#xff0c;执行如右写模式:dd if/dev/zero of/xxx/cephfs bs6K count4 oflagdirect 关键配置&#xff1a; bluestore_min_alloc_size_hdd 65536 bluestore分配空间的最小粒度 单位&#xff1a;B…

JVM系列(之ClassLoader)

Class Loader Java运作流程 内部class loader bootstrap class loader --引导类加载器&#xff0c;它负责加载Java的核心类【java.* 】&#xff08;如classpath下面的类库&#xff09;&#xff0c;不是 java.lang.ClassLoader的子类&#xff0c;而是由JVM自身实现的。Code . UR…

java平台类成员访问修饰符_JAVA类的修饰符及访问权限

1.类外部类 class前的修饰符只能有publicfinalabstrct无(默认) &#xff1a;同包可见 (Eclipse中选择package)内部类 class前的修饰符有public、protected、private、默认、final、abstract、static。先看类的访问权限&#xff0c;再看成员的访问权限&#xff0c;类…

ios实例开发精品源码文章推荐

1、IOS代码分享:视图布局&#xff08;View Layout&#xff09;Border View140601bvpw22rir88b9i8i.png(19.97 KB, 下载次数: 0)下载附件保存到相册半小时前 上传http://www.apkbus.com/android-101999-1-14.html2、IOS代码分享&#xff1a;导航条&#xff08;Navigation Bar&am…

Spring BeanDefinitionRegistryPostProcessor BeanPostProcessor作用

写博客&#xff0c;写博客&#xff0c;把自己知道的小知识点全部记录&#xff0c;? BeanDefinitionRegistryPostProcessor 接口属于Beanddefination 装配定义的范畴&#xff0c;此时bean 并没有初始化 BeanPostProcessor属于be an 实例化修改的范畴&#xff0c;be an 已经进行…

关于ceph源码 backtrace 打印函数调用栈

当集中精力看一个问题的时候&#xff0c;时间久了就会有这样一个状态&#xff0c;天空飘来五个字&#xff0c;那都不算事 ceph源码庞大的体量以及复杂的设计让很多人望而却步&#xff0c;尤其是大量的纯虚函数更是让读者迷失在代码的海洋&#xff0c;这个时候函数调用栈是一个救…

泛型java 代码讲解_Java泛型详解

2516326-5475e88a458a09e4.png一&#xff0c;打破砂锅问到底泛型存在的意义&#xff1f;泛型类&#xff0c;泛型接口&#xff0c;泛型方法如何定义&#xff1f;如何限定类型变量&#xff1f;泛型中使用的约束和局限性有哪些&#xff1f;泛型类型的继承规则是什么&#xff1f;泛…

(转)金额转中文大写

public class RMB {//返回转换好的大写形式public static String numberToRMB(String money) {return cleanZero(splitNum(roundString(money)));}// 将小写金额转换成大写金额private static String splitNum(String s) {// 如果传入的是空串则继续返回空串if ("".e…

[IOS]UIWebView实现保存页面和读取服务器端json数据

如何通过viewView保存访问过的页面&#xff1f;和如何获取并解析服务器端发送过来的json数据&#xff1f;通过一个简单的Demo来学习一下吧&#xff01; 操作步骤&#xff1a; 1.创建SingleViewApplication应用&#xff0c;新建VIewController&#xff0c;并在xib试图中添加WebV…

struts2之配置文件struts.xml详解

struts配置文件 struts.xml配置参数详解 struts.xml中很大一部分配置默认配置就好了 但是有些还是需要做了解 以便于理解 和修改 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Str…

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

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

php中怎么过滤器_PHP 过滤器(Filter)

过滤多个输入表单通常由多个输入字段组成。为了避免对 filter_var 或 filter_input 重复调用&#xff0c;我们可以使用 filter_var_array 或 the filter_input_array 函数。在本例中&#xff0c;我们使用 filter_input_array() 函数来过滤三个 GET 变量。接收到的 GET 变量是一…

c++ Qt向PHP接口POST文件流

Qt调用PHP写的接口&#xff0c;向其传递图片文件&#xff0c;并保存在服务器。 二进制文件无法直接传递&#xff0c;Qt采用Base64进行编码发送&#xff0c;PHP解码保存为文件。 注意&#xff1a;PHP收到数据之后会将POST过来的数据中的加号()替换为空格&#xff0c;造成接收到的…

在网络通讯中应用Protobuf

Protobuf的设计非常适用于在网络通讯中的数据载体&#xff0c;它序列化出来的数据量少再加上以K-V的方式来存储数据&#xff0c;对消息的版本兼容性非常强&#xff1b;还有一个比较大的优点就是有着很多的语言平台支持。下面讲解一下如何在TCP通讯应用中集成Protobuf. Protobuf…

JS中Math函数的常用方法

Math 是数学函数&#xff0c;但又属于对象数据类型 typeof Math > ‘object’ console.dir(Math) 查看Math的所有函数方法。 1&#xff0c;Math.abs() 获取绝对值 Math.abs(-12) 12 2&#xff0c;Math.ceil() and Math.floor() 向上取整和向下取整 console.log(Math.ceil(1…

C++ 泛型编程 -- 函数模版

文章目录定义声明调用方式函数模版的重载函数模版的特点工作中一个同事写了测试demo&#xff0c;想要自己尝试使用发现调用老出错&#xff0c;请教的时候发现是函数模版&#xff0c;有自己的调用方式&#xff0c;并且发现核心代码中大量的函数模版和类模版。特此做一个函数模版…

bellman_ford寻找平均权值最小的回路

给定一个有向图&#xff0c;如果存在平均值最小的回路&#xff0c;输出平均值。 使用二分法求解&#xff0c;对于一个猜测值mid&#xff0c;判断是否存在平均值小于mid的回路 如果存在平均值小于mid的包含k条边的回路&#xff0c;那么有w1w2w3...wk < k * mid,即(w1-mid)(w2…

守护进程中创建的对象php,在PHP中生成守护进程(Daemon Process)

前两天看到一篇文章《如何使用PHP编写daemon process》&#xff0c;其中对核心代码却没有细说&#xff0c;我又查了一些资料&#xff0c;还看了一本《理解Unix进程》&#xff0c;才搞明白生成守护进程的时候发生了什么。这段代码是这个样子的&#xff1a;function run(){//第一…

log4j个人使用整理

Log4j介绍&#xff1a; 略过。 配置&#xff1a; Eclipse项目中添加log4j.jar到lib下。 在bin目录下新建log4j.properties&#xff0c;编辑好log4j配置文件。 样例分析&#xff1a; 1 log4j.rootLoggerWARN, stdout, file2 log4j.appender.stdoutorg.apache.log4j.ConsoleAppen…

完全理解 Python 迭代对象、迭代器、生成器(转)

完全理解 Python 迭代对象、迭代器、生成器 本文源自RQ作者的一篇博文&#xff0c;原文是Iterables vs. Iterators vs. Generators nvie.com&#xff0c;俺写的这篇文章是按照自己的理解做的参考翻译&#xff0c;算不上是原文的中译版本&#xff0c;推荐阅读原文&#xff0c;谢…

Rocksdb 与 TitanDb 原理分析 及 性能对比测试

文章目录前言Rocksdb的compaction机制compaction作用compaction分类level style compaction&#xff08;rocksdb 默认进行的compaction策略&#xff09;level 的文件存储结构compaction过程compaction中的level target sizeuniversal style compactionfifo style compactionTit…