单机Mem冷热追踪

本文涉及的产品
推荐全链路深度定制开发平台,高级版 1个月
简介: 从实际使用的角度,通过追踪page冷热,实现另一种swap

阿里巴巴搜索事业部几乎负责了阿里所有的搜索业务,hippo 调度系统为这些业务服务,提供资源抽象和分配,业务管理与调度的能力。提供了可靠、简单、低成本的资源及应用托管方案,已经在搜索,蚂蚁,广告,菜鸟等BU稳定运行5年多。

对上, 调度系统提供资源抽象能力,computers as computer。
对下, 调度系统提供资源隔离与超卖能力,又让马儿跑,又让马儿少吃草。

所以在16,17年之间,hippo团队提供了单机Mem Qos功能,简单说提供了资源超卖和保障资源质量的功能。通过实时资源使用预估,在离线Mem超卖,在离线Mem比例控制,用户态OOM,资源通信协议等手段,在保证Mem质量的情况下,最大化单机Mem资源数量,达到省钱的目的。这篇文章主要涉及近期冷内存相关的工作,这个工作是Mem Qos的良性补充,从更合理的角度考量内存的使用和回收机制。

Qos泥泞路

自打mem超卖上线以来,就遇到了很多问题,绕不开的两个问题是:

第一个:超卖带来的资源质量问题
第二个:Mem资源使用审计/数数问题

质量问题

资源质量主要描述一份资源的可服务能力。以cpu为例,可以用单位时间处理的指令数衡量,以disk,mem为例可以用访问延时衡量。举例来说同样一份80G内存的分配计划,落到一个很idle的机器上,和落到一个很busy的机器上完全是两个世界。

在Qos生效的这一年里,我们不断的遇到bad case。最典型的就是:mem紧张,导致mem和disk频繁颠簸。这样mem访问延时比正常的差几个数量级,资源质量极速下降。而且整机颠簸影响的不只这一个app,还会影响旁边的人。做人力争利人利己,万不得已,尽量不要损人,这是我们行走一生的哲学,但在这里,在机器世界里,不同app之间,明目张胆的战争和私底下的偷偷摸摸才是生活的全部。另一个例子是我们没有很好的刻画app mem使用的成分情况,有可能会出现几个基本都是匿名页的app堆在一起,流量高峰的时候,匿名页是大户,page cache很少,没有reclaim的余地,系统只能OOM。

造成这个问题的典型场景就是:一个hippo管理之外的程序用了很多mem,和hippo的分配计划撞到一起了。资源质量下降的一个影响是业务超时,另一个影响是单机Qos模块会频繁生效,会杀离线,但部分离线任务的failover代价巨大,而且在机器mem严重短缺的时候,Qos模块能不能100%工作都是谜。

数量问题

调度系统做调度决策需要数据支持,根据单机资源使用情况决定任务的上与下,可以说资源使用审计质量从很大程度上影响了调度决策的质量。cpu,disk的使用审计是简单明确的,但在mem资源使用审计上我们遇到了一些问题。

传统linux风格的系统在管理mem时,基本采取激进分配,lazy回收的做法,倾向于把更多的mem分配出去当作cache,这给实际working set的统计带来困难。传统的working set采集方式,一般会按根据page的类型和所处位置来计算,比如:

active_anon + inactive_anon + active_file + inactive_file * p + unevictable

这个方法里有几个问题:anon的就一定得算在working set里?  这个p该取何值?unevitable里的就一定很“被需要”?

先暂且搁置这些问题,我们快速非严谨的看看linux是如何管理page的。内核里用LRU链表管理page,有active和inactive两个list。但你觉的内核里的LRU list是你想象的样子,按照时钟,长时间没用就挪到inactive list里?内核里是用相对排序和一些启发式策略决定一个page是应该在active里还是在inactive里,而且绝对不是实时排序的,只在那么几个特殊的埋点挪一挪。所以可能会出现经常访问的page呆在inactive list里,很久没有访问的page呆在active list里,而且一个page在list中的顺序基本不会因为这个page被access而改变。

如果没有内存回收动作,你可以认为LRU list是锁死的,那玩意不会实时update的,充分实践lazy策略,这给我们判断哪部分page是hot的带来了困惑。举个例子,短时间集中访问的文件页,假如这些page在active file list里,在这波访问结束后,这些page不再被使用的话,这些page是事实上free的。但在目前的策略下,这些page会长时间呆在active file list里,直到下次内存回收,才会触发迁移,有可能搬移到inactive file list里。

内核里用一些bit来记录某个page是否被访问,这些bit记录能力有限,它记录的不是整个page生命周期的使用情况,更多的是回收前的一次访问或者回收扫描周期内的访问情况。这样LRU的语义就大打折扣,用这个active和inactive来决定working set,是不合适的。

cgroup 和 proc统计都有类似的问题,你只能得到一个粗略的数字,但真正有用的其是一个类似访问分布的东西,我们站在使用者的层面,站在上帝视角,抛开内核的沟沟坎坎,可以在脑海中想象这样的一幅图:
image.png

横坐标是page的index,纵坐标是一个时间窗口内page被访问的频率或次数,拿着这个图,你能得到一些信息,然后搞搞小动作:

  • 如果要选择一些页牺牲掉,傻子都知道咋选,如果你跟我杠,说这个page很快就要被大量使用了,我选择投降。
  • 在这个图上,横着画一条线,纵轴超过这个线的page可以认为是很hot的,这些page就可以当作working set,管他是anon的,还是file的,管他在active的list里,还是在inactive的list里,管他有没有加lock。比如上图的1,3,5,7号page就可以认为是很hot的,0,2,4,6 是比较idle的。
  • 这个线的高低可以per group的决定,是不是感觉很美好?其实不光可以画一条线,你可以画两条,比如在上图中,在25那个位置再画一条线,超过50的就是这app最hot部分,要保证这些page的安全。25到50之间的是warm的page,尽量留在RAM里好了,比如6号page。低于25的,就是混日子的,换到磁盘上也没啥事,比如0,2,4号page。

所以我们需要把这些低水位下的page当作是“free”的,可以给别人用的,这是我们“冷内存”项目最初的motivation

冷内存项目

“当成free的”主要有两个事情要做:

  • 第一个:这些free的是谁,有多少。涉及到统计问题
  • 第二个:这些free的page在需要腾地方的时候要真的能free掉。涉及到回收问题

统计相关:

统计问题是2017年开始的。简单说就是利用和改造“Idle Page Tracking”技术,为每个物理页定义 idle age,保存物理页空闲年龄,然后周期性的扫描RAM,查看这个page最近是否被access过,再通过page结构的cg指针找到这个page是charge到哪个group上的,这样就能得到每个mem cg的mem cold统计直方图。

利用这个数据,我们可以根据业务特点给每个mem cg设置不同的水位,就能知道每个group的cold内存到底有多少,working set到底有多大。

回收相关:

另一个很重要的问题是识别之后的回收动作。
这些水位线以下的,长时间不访问的page如何回收?传统的kswap肯定不好使,因为他没有按照我们的算法pick页,效率也不好。另一个,我们是站在实际访问的角度来判断一个page是hot,warm,还是cold的,和这个page的类型[anon的还是file的],所处位置[在active list里,还是在inactive list里],一些特殊标记[比如lock标记]等都没有关系。为了达到这个目的,我们需要做很多工作,比如我们需要打破mlock的语义。

也要支持不同mem cg定义自己的水线,是否参与这个过程,也要结合mem cg的优先级。在回收模型上,我们考虑了周期性一刀切模型,梯度回收模型,也讨论了复用已有mem cg参数的可能。内核回收模块也经历了“target machine”的设计和“target mem cg”的设计,一切都在有序的开展。在这个过程中,也顺带发现了不少内核的bug:比较典型的是page回写和jdb2导致的死锁问题;mem cg 读频繁导致个别业务超时问题;2018年11前夕为安全计,我们灰度了2000台一刀切模型,其中随机挑选的一批500台数据简单总结如下:

单机free变化 iowait变化 磁盘读写变化 major page fault变化 业务延迟变化
增加110G 不明显 不明显 略有增加 不明显

没感受到回收冷内存会给业务延时造成影响。

后续工作

这个项目还没有结束,还有想象空间,比如:

  • 目前我们的版本还比较粗糙,因为idle page统计需要扫描整个RAM,所以实时性不好,用这个来计算working set还是不合适,我们需要一个实时的,准确的按照实际访问频率角度,或其他有意义的working set计算方式,目前我们依然采用anon+lock的当作used,file page都算做是free的。但如果我们站在另一个角度,使用一刀切模型,如果这个模型工作的很好,能留在RAM里的基本都是hot的,就可以算作是working set。
  • 目前从现象上看冷内存回收会导致iowait突高,需要后续修复
  • 目前我们只考虑了clean file page,anon page,dirty file page也可以考虑起来
  • 存储计算分离有可能会使用tempfs,可能后续也需要考虑这种情况
  • swap和冷内存回收如何相处?考虑anon,tempfs,aep或者optane之后呢?

小结

mem单机资源控制诞生大概两年的时间了,bad case 不少。有些能在单机端解决,比如尽早回收cold page,缓解单机压力。有些需要在scheduler端解决,比如简单的:单机available少的机器降权,也能避免个别单机mem压力大导致的问题。总之还有很多事情可以考虑和尝试,没有什么是一开始就设计好的,跌跌撞撞的前行吧。

目录
相关文章
|
6月前
|
存储 缓存 固态存储
存储性能的关键指标:IOPS与吞吐量详解
【4月更文挑战第21天】
2181 0
|
6月前
|
存储 缓存 分布式计算
亿级数据如何分钟级别写入缓存?
亿级数据如何分钟级别写入缓存?
52 0
|
1月前
|
存储 监控 固态存储
在高并发环境下,如何优化 WAL 的写入性能?
在高并发环境下,如何优化 WAL 的写入性能?
|
4月前
|
存储 缓存 中间件
|
4月前
|
存储 JSON 监控
日志存储问题之日志存储降低优化是针对哪种日志进行的
日志存储问题之日志存储降低优化是针对哪种日志进行的
|
3月前
|
存储 缓存 算法
优化 ChunkServer 的存储性能
【8月更文第30天】在分布式文件系统中,ChunkServer 是负责存储数据块的关键组件。为了提高ChunkServer的存储性能,可以通过多种技术手段进行优化,如缓存、压缩、并行处理等。本文将详细讨论这些技术的应用,并提供具体的代码示例。
37 0
|
4月前
|
存储 监控 算法
高性能存储 SIG 月度动态:优化 xfs dax reflink 时延,独立选型并维护 mdadm 和 ledmon
高性能存储 SIG 月度动态:优化 xfs dax reflink 时延,独立选型并维护 mdadm 和 ledmon。
|
4月前
|
缓存 关系型数据库 MySQL
实时计算 Flink版产品使用问题之缓存内存占用较大一般是什么导致的
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
12月前
|
算法 数据库 异构计算
Milvus 2.3.功能全面升级,核心组件再升级,超低延迟、高准确度、MMap一触开启数据处理量翻倍、支持GPU使用!
Milvus 2.3.功能全面升级,核心组件再升级,超低延迟、高准确度、MMap一触开启数据处理量翻倍、支持GPU使用!
Milvus 2.3.功能全面升级,核心组件再升级,超低延迟、高准确度、MMap一触开启数据处理量翻倍、支持GPU使用!
|
存储 弹性计算 固态存储
三分钟磁盘存储性能IOPS、I/O及吞吐量指标详解
磁盘存储性能指标IOPS是什么?磁盘I/O和吞吐量是指什么?详细说下磁盘存储性能指标I/O、吞吐量和IOPS之间的关系及意义,以阿里云服务器为例,来详细说下高IO磁盘性能使用场景及ECS云服务器实例规格选择: