[230527] Page Cache

PageCache是操作系统用来缓存磁盘数据的内存区域,通过LRU算法管理,优化磁盘IO。Linux使用active_list和inactive_list分层次处理预读和访问数据,防止预读失效。而在批量读取时可能导致热数据被挤出,通过延迟晋升策略来缓解缓存污染问题。
摘要由CSDN通过智能技术生成

[230527] Page Cache

上个月某一天旷视一面,面试官问 Page Cache,我居然脑子里一点东西都没有,很懊悔面试体验很糟糕。虽然后来被男朋友带去吃京华烟云被哄好了,但不应该只解决情绪,解决完情绪还需要解决问题555。血的教训!!

1 Page Cache 是什么

Page Cache 是属于内存空间里的数据,因为访问内存会比访问磁盘快很多,所以操作系统会对读取的数据进行缓存。当下一次访问相同的数据时,就不需要通过磁盘 IO 了,命中缓存直接返回数据即可。

2 如何管理 Page Cache:LRU 算法

Linux 的 Page Cache 和 MySQL 的 Buffer Pool 的大小是有限的,并不能无限的缓存数据,对于一些频繁访问的数据我们希望可以一直留在内存中,而一些很少访问的数据希望可以在某些时机可以淘汰掉,从而保证内存不会因为满了而导致无法再缓存新的数据,同时还能保证常用数据留在内存中。操作系统一般使用 LRU 算法来管理 Page Cache。

LRU 一般使用链表来实现,思路如下:

  • 当访问的页在内存里,就直接把该页对应的 LRU 链表节点移动到链表头部。
  • 当访问的页不在内存里,要检查链表是否已满,如果满了,要先删除链尾的页,然后把该页加入到链表头部。

3 LRU 算法可能存在的问题及其优化

1. 操作系统在读磁盘时会额外多读一些到内存中,但最后这些数据也没用到,有什么改善方法吗?

这个描述的是操作系统的预读机制(基于局部性原理)和可能产生的预读失效的问题。在传统的 LRU 算法里面,会把预读的数据全部放到链表的头部,如果数据过多,还会把尾部的页淘汰掉。

Linux 操作系统通过改进 LRU 链表来改善这个问题,它设置了两个LRU 链表:活跃 LRU 链表(active_list)和非活跃 LRU 链表(inactive_list)。其中:

  • active_list 存放最近被访问过的内存页
  • inactive_list 存放很少被访问的内存页

操作系统预读的数据(预读页)会被放到 inactive_list 的头部,如果预读的数据被真正访问到了,就会把它插入 active_list 的头部。

补充一点:active_list 尾部的页是不会被淘汰的,而是会被降级到 inactive_list 的头部,只有 inactive_list 尾部的页会被淘汰。

2. 批量读取数据的时候,可能会把热数据(常访问的数据)挤出去,这个有什么改善的方法呢?

这是缓存污染的问题。这个场景放在 MySQL 的缓存里比较好理解,当执行一个 SQL 语句的时候,它可能扫描了大量的数据,在 Buffer Pool 空间有限的情况下,会把 Buffer Pool 中的数据全部替换掉,但新读取的数据可能用了一次就用不上了,而需要访问之前那些热数据时又无法命中。所以命中率急剧下降。

这个问题可以通过提高冷数据变成热数据的门槛来改善:

  • 在 Linux 操作系统中,当内存页被命中第二次时,才会把页从 inactive_list 升级到 active_list
  • 在 MySQL Innodb里,当内存页被命中第二次时,还会对两次访问的时间间隔进行判断:
    • 若时间间隔在 1 秒内,则不会把内存页从 old 区升级到 young 区
    • 若时间间隔超过 1 秒,则会把该内存页从 old 区升级到 young 区
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值