Linux内存管理优化:面向低延迟/高吞吐量数据库GraphDB

2013-10-12 09:35:18 | 新闻来源:叶凡网络 | 点击量:1063

      这样我就能够重复使用这些片段,通过这种方式,已经为自己的存储系统添加了片段池。降低了需要创立的文件数量,同时减小了对Linux页面缓存造成的处置压力。通过初步测试,发现片段池机制带来了令人鼓舞的逊色效果。

简介

      而且能够直接处置所有正处于执行当中的查询。GraphDBLinkedIn实时分布式社交图谱服务当中充任着存储层的角色。服务旨在处置简单查询(例如来自LinkedIn成员的一级与二级网络请求)与复杂查询(例如成员之间的距离以及成员之间的关联路径等图谱结果)支持多种节点及边界类型。对应用程序使用我社交图谱的方式进行初步了解。

      而且99%查询都能在微秒级别的延迟之内得到响应(通常延迟为十几微秒)有鉴于此,LinkedIn上的每一个页面视图都会发生多条指向GraphDB查询请求。这意味着GraphDB每秒钟都要处置不可胜数条查询请求。即使GraphDB响应延迟提高到仅仅5毫秒,LinkedIn全局访问效果也将受到严重影响。

      已经发现GraphDB会在使用高峰当中偶尔出现间歇性响应延迟。深入调查了这些高峰时段,2013年的大部分时段。并努力了解Linux内核如何管理NUMA 即非统一内存访问)系统上的虚拟内存。概括来说,针对NUMA 一部分Linux优化存在严重的负面作用,会因此对延迟发生直接性不利影响。认为此次研究的效果足以协助任何一套运行在Linux系统环境下、对延迟要求较高的线数据库系统获得性能改进。经过我优化调整,问题出现几率(例如响应缓慢或者查询超时的出现比例)已经下降到原先的四分之一。

      将共同了解相关背景资料,文章的第一部分。包括:GraphDB数据管理方面的流程大纲、性能问题的具体表示以及Linux虚拟内存管理(简称VMM子系统的运作方式。文章的第二部分,将详细探讨解决方法、指导意见以及结论汇总,旨在通过实验找到问题呈现的根源。最后,将归纳通过此次实例所获得的经验。

本文适合对操作系统运行机制具备一定了解的朋友。


背景资料

1、GraphDB如何管理数据

      将所有数据文件映射到虚拟内存页面当中,GraphDB实质上是一种内存内数据库。读取方面。并始终将其保留在内存中的活动集之下。读取活动具备很强的随机性,指向目标普及整个数据集,且99%请求都要求将延迟控制在微秒级别。一台典型的GraphDB主机能够拥有48GB物理内存,常用内存量为20GB其中15GB用于处置堆外虚拟内存页面映射数据,5GB用于JVM堆。

      拥有一套日志-结构化存储系统。将全部数据划分为以10MB为单位的纯追加部分。目前,而在写入方面。每一台GraphDB主机大约拥有1500个活动部分,其中只有25个能够随时接受写入操作,其它1475个则处于只读状态。

      需要定期对其进行压缩。此外,由于数据采用日志结构化存储方式。由于我所采取的压缩计划比较积极,因此每天每台主机上约有九百个数据片段会被遗弃。换言之,每天每台主机上约有容量达9GB数据文件完全消失,但这还仅仅是LinkedIn全局数据增量中的一小局部。概括来讲,每台48GB主机在运行五天之后页面缓存就会被垃圾堆满。

2、问题症状

      往往会面临数量庞大的直接页面扫描以及内存执行效率低下等困扰,所遇到性能问题主要表示为在使用高峰期GraphDB出现响应延迟。高峰期呈现的同时。具体情况如sar所示。个别情况下,sar-B 下"每秒pqsandpqscand/"列的输出效率将拖慢至每秒100万到500万页面扫描,虚拟内存效率也会降至0%--这些症状往往会继续数小时。

      系统的内存压力却并不明显:这是因为我可以通过/proc/meminfo记录看到大量无效缓存页面。此外,性能表示急剧下滑的过程中。并不是pqscand/中的所有高峰时段都会引发GraphDB延迟问题。

3、最让我感到困惑的两个问题是

      为什么系统内核会对页面进行扫描?1如果系统中不存在明显的内存压力。

      为什么我响应延迟会急剧升高?只有写入线程需要占用新的内存分配,2即使内核开始对页面进行扫描。而且写入与读取线程池是相互独立的因此,为什么实际结果是双方会相互发生影响?

      别担心,正是这些问题的答案促使我对NUMA 系统的Linux优化方案做出调整。需要强调的最终将注意力集中在Linux"区回收(zonereclaim"功能方面。如果大家对于NUMA Linux以及区回收不太了解。会在下一局部内容中做出详细讲解。这些资料的辅助下,大家应该可以顺利理解文章其它局部的论证过程。

4、关于LinuxNUMA 以及区回收的那些事儿

      首先需要明确Linux系统如何处置NUMA 架构。为大家甄选了一部分优秀的讲解资源,要想深入理解问题发生的根源。希望能协助各位快速掌握相关的背景知识:

  • JeffFrostLinux中的PostgreSQLNUMA 以及区回收模式》如果大家时间有限,优先推荐各位阅读这篇文章。
  • ChristophLamet非统一内存访问概述大家需要着重阅读其中关于Linux如何从NUMA 区中回收内存的局部。
  • JeremiColeMySQL交换错乱”问题以及NUMA 架构的影响

同样重要的大家需要理解Linux从页面缓存中使用回收页面的具体机制。

      Linux为每个NUMA 区保管着一组三个页面列表:活动列表、非活动列表以及空闲列表。新页面进行分配时会被从空闲列表转移到活动列表。而LRU算法则负责将页面从活动列表转移到非活动列表,简而言之。而后再由非活动列表转移至空闲列表。下面我为大家推荐一份学习Linux页面缓存管理知识的最佳资料:

      而后尝试关闭掉生产主机上的区回收模式。关闭之后,首先认真阅读了上述资料。性能表示立刻获得显著提升。有鉴于此,决定在本文中详细描述区回收的运作机制以及对性能造成影响的原因。

     如果大家对区回收还不太熟悉,本文的其它内容深入探讨了Linux区回收的相关内容。请首先阅读前文推荐的JeffFrost相关论述。


重现并理解Linux区回收活动

1、设置实验环境

      编写了一款程序,为了理解区回收的触发原理以及区回收如何影响性能表示。用于模拟GraphDB读取与写入活动。以二十四小时为期限运行该程序,前面十七个小时内、开启了区回收模式。而在最后七个小时中,关闭了区回收模式。该程序在整个二十四小时当中不间断地运行,环境中的惟一变化就是第十七小时通过向/proc/sys/vm/zone_reclaim_mod中写入"0"来禁用区回收。

下面我来解读该程序的运行内容:

     全部读取一遍,1将2500个10MB数据文件映射至页面缓存当中。而后取消映射,这样Linux页面缓存当中就充溢着垃圾数据。如此一来,系统的运行状态类似于GraphDB主机在正常运行数天后的情况。

      再随机读取其中的一部分内容。这2500个文件构成了活动集合,2一组读取线程会将另一组2500个10MB文件映射至页面缓存当中。用于模拟GraphDB日常使用中的读取状态。

      写入线程就会从活动集合中随机挑选一个文件、取消其映射并用刚刚创立的新文件加以取代。这一过程旨在模拟GraphDB日常使用中的写入活动。3一组写入进程不时创立10MB文件。一旦某个文件创建完成。

      如果读取线程完成读取所消耗的时间超越100毫秒,4最后。则自动输出该次访问流程的usrsy以及elapstime这使我得以胜利追踪到读取性能的变化轨迹。

      保证主机不会遇到任何形式的内存压力。用于运行该程序的主机拥有48GB物理内存。工作组大约占用了其中的25GB除此之外系统中没有运行其它任何任务。通过这种方式。

2、解区回收机制如何被触发

      系统内核会首先检查首选NUMA 区是否拥有足够的空余内存以及是否存在1%以上可以回收的页面。这一百分比可以调节,当某个进程针对页面发出请求时。并由vm.min_unmapped_ratiosysctl来决定。可回收页面属于由文件支持的页面(即与页面缓存存在映射关系的文件所产生的页面)但其目前并未被映射到任何进程当中。/proc/meminfo中,可以很清楚地看到所谓"可回收页面(reclaimpage"就是那些"活动(文件)-非活动(文件)-被映射"Activefile+Inactivfile-Map内容。

       并搭配如下所示的"低/中/高(low/min/high"标签:那么系统内核如何判断多少空闲内存才够用呢?内存会使用区"水平标志(watermark"通过/proc/sys/vm/min_free_kbyt中的值来进行判断。同时也会检查/proc/sys/vm/lowmem_reserve_ratio中的值。特定主机内经过计算的值会被保存在/proc/zoneinfo当中。

Node 1, zone Normal 

  • pages free 17353 min 11284 
  • low 14105 high 16926 
  • scanned 0 spanned 6291456 
  • present 6205440 

          页面回收操作就会中止。此外,内存会在区内空闲页面数量低于水平标志时执行页面回收。而当空闲页面的数量高于"低"水平标志后。这一计算过程针对的各独立区:即使其它区仍拥有足够的空闲内存,只要当前区被触发,回收机制就会付诸实施。

    下面我通过图表来展示实验过程中的活动表示。其中值得注意的包括以下几点:

    • 黑色线条代表区中的页面扫描,并以右侧的y轴为基准生成图形。
    • 红色线条代表区中的空闲页面数量。
    • 绿色线条代表的"低"水平标志。

          观察到与生产主机类似的表示。所有情况下,通过实验。页面扫描情况都与空闲页面情况坚持吻合--二者的数值恰好相反。换句话来说,Linux会在空闲页面数量低于"低"水平标志时触发区回收机制。

    3、系统区回收机制的特性

          下面我将关注重点放在其它方面--区回收模式如何影响性能表示。为了实现这一目标,理解了区回收模式的触发原理。实验过程中每秒一次收集来自下列源的信息:

    1. /proc/zoneinfo
    2. /proc/vmstat
    3. /proc/meminfo
    4. numactl-H

          发现了一些非常有趣的特性--这些特性正是解答区回收机制对读取性能发生负面影响的关键所在根据这些文件中的数据绘制图表并总结活动模式后。

         区回收机制处于启用状态,前期观察中。这时Linux执行的大多是直接回收(即回收任务在应用顺序线程内直接执行,并被计作直接页面扫描)一旦区回收模式被关闭,直接回收活动立刻停止,但由kswapd执行的回收数量却开始增加。这就解释了为何会在sar中观察到每秒pqscand如此之高:

          即使我读取与写入操作并未发生变化,其次。Linux活动与非活动列表内的页面数量也在区回收模式关闭后发生了显著变化。需要强调的区回收机制的开启时,Linux会在活动列表中保留总大小约20GB页面信息。而在区回收机制关闭后,Linux活动列表内的信息保管量增加到约25GB这正是整个工作集的大小:

     

    观察到区回收模式被关闭后,第一。页面内活动出现了显著差异。值得关注的一点在于,虽然从页面缓存到磁盘驻留的速率坚持不变,但区回收被关闭后从磁盘驻留到页面内的速率显著降低。主要故障率的变化情况与页面内传输速率完全一致。下面的图表证明了这一结论:

     

    发现顺序中的高占用内存访问活动的数量在区回收模式被关闭后大幅减少。以下图表显示了内存访问延迟(单位为毫秒)以及响应时间在系统及用户CPU层面的具体消耗。可以看到该程序的大部分运行时间被消耗在I/O等待方面,最后。而且偶尔还会在系统CPU当中遭遇阻塞。

    4、区回收模式如何影响读取性能

          看起来由区回收所触发的直接回收途径似乎在将页面从活动列表中移除并转移到非活动列表方面表示得太过激进。特别是区回收机制启用时,基于以上统计结果。活动页面似乎会被直接清盘并被塞进非活动列表,而后再被移出到空闲列表当中。有鉴于此,读取活动会遭遇极高的主要故障机率,性能表示也变得一落千丈。

          作为直接回收路径的组成局部、似乎在区中采用了一种全局自旋锁,导致问题进一步加剧的则是shrink_inactive_list函数。从而阻止其它线程在回收过程中对区产生修改。正因为如此,才会在高峰时段发现系统CPU读取线程中出现锁定,这很可能是因为多个线程之间存在抵触。


    NUMA 内存平衡机制同样会触发直接页面扫描

          也证实了这类将页面数据挤出活动列表的粗暴扫描正是读取性能下滑的罪魁祸首。除了区回收之外,刚刚了解了区回收模式如何触发直接页面扫描。还发现一项名为TransparHugePag简称THP红帽Linux功能在对NUMA 区进行内存"平衡调整"时同样会触发直接页面扫描。

          系统会以透明化方式为匿名(即非文件支持)内存分配2MB"大型页面"这种做法能够提高TLB中的命中率并降低系统中页面列表的大小。红帽方面表示,THP功能的推动下。THP特定工作负载中能够带来高达10%性能提升。

          由于这项功能以透明化方式运作,另外。因此它还利用一局部代码将大型页面分割成多个常规页面(/proc/vmsat中被统计为thp_split或者将多个惯例页面汇聚成巨大页面(被统计为thp_collaps

          thp_split仍然会导致很高的直接页面扫描比率。还发现Linux系统会将我5GBJava堆分割成巨大页面,已经看到即使区中不存在内存压力。从而将其在不同NUMA 区之间进行移动。大家请看如下图表:总大小约5GB来自两个NUMA 区的数据被分割成巨大页面,其中一部分被从Node1移动到Node0这类活动肯定会带来很高的直接页面扫描比率。

          而且这似乎也不能算是导致直接页面扫描的罕见原因。不过我手中有大量数据可以证明,无法在自己的实验环境下重现这一状况。TransparHugePag功能与NUMA 系统的协作效果并不理想,因此我决定在自己的RHEL设备上运行下列命令来禁用该功能。

    echo never > /sys/kernel/mm/transparent_hugepage/enabled 

    经验教训

    0,1LinuxNUMA 优化对于典型数据库负载并无意义

           而NUMA 优化并不能做到这一点。需要强调的利用内存缓存规避磁盘读写所节约的时间要远远逾越将内存接入多插槽系统中特定插槽所换来的延迟改进。数据库的主要性能提升源自在内存中对大量数据进行缓存处理。

    从而提高性能表示:LinuxNUMA 优化机制可以通过以下几种方式禁用。

    • 关闭区回收模式:向 /etc/sysctl.conf中添加vm.zone_reclaim_mod=0并运行sysctl-p以载入新设定。
    • 为自己的应用顺序启用NUMA 交叉存取功能:运行应用时加入numactl--interleave=al命令。

    以上两种设置已经成为我全部生产系统中的默认状态。

    0,2不要对Linux设置掉以轻心:亲手管理页面缓存中的垃圾内容

          因此接受着时间的推移我Linux页面缓存中产生了大量垃圾内容。事实证明,由于GraphDB日志结构化存储系统无法重新使用其数据片段。Linux正确清理这类垃圾内容时表示得相当糟糕:通常会不由分说地把一切数据扔进废纸篓,这种过分激进的处置方式令我读取性能遭遇极高的主要故障比率。直接回收与kswapd都起到助纣为虐的作用,但前者的负面作用更为明显。


  • 公司名称:合肥叶凡网络科技有限公司
    网站建设网址:http://www.hfyefan.com/web.html
    网站优化网址:http://www.hfyefan.com/promotion.html
    热线:400-0551-422
    电话:0551-5867402
    业务QQ:446881654
    邮箱:web@hfyefan.com

  • 上一篇:美媒:斯诺登在俄交女友 是否为俄女间谍成谜 下一篇:2013年10月编程语言排行榜:Groovy首次闯入前二十