关于influxdb:Influxdb进程内存占用异常分析

景象

  • 07/09 15:00:

    • 一波海量申请,向OS申请内存,拉高了heap_sys、heap_inuse;
  • 07/09 15:24:

    • 流量峰值过来当前,heap_inuse降下来了(100MB),然而heap_idle还是很高(500MB),导致整体RSS很高;

背景常识

Influxdb的内存要害指标:

  • go_memstats_heap_sys_bytes:go过程从OS获取的heap内存;
  • go_memstats_heap_idle_bytes: golang过程中暂未应用的heap内存;
  • go_memstats_heap_inuse_bytes: golang过程以后heap理论应用的内存;
go_memstats_heap_sys_bytes = go_memstats_heap_idle_bytes +  go_memstats_heap_inuse_bytes

从监控图上能够看出,申请过后heap_idle_bytes依然很高,阐明被heap占着没有开释。

起因剖析

heap_idle为什么不立刻开释:

  • heap_idle是指存在heap内,临时没有被应用,然而给runtime预留的空间;
  • 没有归还给OS是因为,应答前面app对内存的应用,不必再去OS申请了;
  • 当产生内存压力的时候,OS会开释掉这块内存,然而“感触到内存压力”可能因为判断不精确,导致OS内的其它过程因为申请不到内存而被OOM;

Go开释内存的策略:

  • Go底层用mmap申请内存,用madvise开释内存,参考go/src/runtime/mem_linux.go的代码:
  • madvise将某段内存标记为不再应用时,有2种形式:

    • MADV_DONTNEED标记过的内存如果再次应用,会触发缺页中断(page fault);
    • MADV_FREE标记过的内存,内核会期待内存缓和时才会开释;在开释之前,这块内存仍然能够服用;(linux 4.5版本内核开始反对)
    • 显然,MADV_FREE是一种空间换工夫的优化;

heap_idle没有被开释的起因是:Go madvise=MADV_FREE,内存被runtime预留没有开释。

解决办法

madvise默认配置:

  • Go1.12之前,linux平台下Go runtime应用madvise==MADV_DONTNEED;
  • Go1.12之后,在MADV_FREE可用时默认优先应用MADV_FREE,当然,用户能够在执行程序前增加GODEBUG=madvdontneed=1来批改这一行为;
  • Go1.16(含)之后,为了避免引起混同,Go官网将madvise默认批改为MADV_DONTNEED;

    • commit: https://github.com/golang/go/…

故能够选用的解决办法:

  • 执行influx过程时,增加GODEBUG=madvdontneed=1参数,强制批改为MADV_DONTNEED;
  • 将influx降级为Go1.16,因为它默认=MADV_DONTNEED;

参考

  1. https://zhuanlan.zhihu.com/p/…
  2. https://github.com/AlexiaChen…
  3. https://github.com/golang/go/…
  4. https://github.com/golang/go/…
  5. https://github.com/VictoriaMe…

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年50元

阿里云限时活动-2核2G-5M带宽-60G SSD-1000G月流量 ,特惠价99元/年(原价1234.2元/年,可以直接买3年),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

You may also like...

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据