news 2026/8/27 14:51:45

LRU缓存淘汰机制全揭秘:SDURLCache如何守护你的磁盘容量上限

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LRU缓存淘汰机制全揭秘:SDURLCache如何守护你的磁盘容量上限

LRU缓存淘汰机制全揭秘:SDURLCache如何守护你的磁盘容量上限

【免费下载链接】SDURLCacheURLCache subclass with on-disk cache support on iPhone/iPad. Forked for speed!项目地址: https://gitcode.com/gh_mirrors/sdu/SDURLCache

SDURLCache 是一个为 iPhone/iPad 上 NSURLCache 提供磁盘缓存支持的开源库,它内置基于LRU 缓存淘汰算法的自动清理机制,确保磁盘缓存使用量永远不超过你设定的容量上限。本文将用通俗的方式拆解它的完整淘汰流程。

为什么磁盘缓存需要 LRU 淘汰机制?

移动端 App 的 HTTP 响应缓存如果只进不出,迟早会塞满磁盘:

  • 缓存文件越写越多,磁盘容量上限被突破
  • 淘汰策略选择不当,还会误删"最近还在用"的热数据
  • 清理如果跑在主线程,会直接卡死 UI

LRU(Least Recently Used,最近最少使用)是工业界最经典的解法:容量超限时,优先淘汰最久没被访问过的条目,把空间留给高频使用的数据。SDURLCache 正是靠这套机制,把磁盘占用牢牢锁在diskCapacity之内。

第一步:给每条缓存建立"档案"

淘汰的前提是知道"谁多大、多久没用了"。SDURLCache 在缓存目录下维护一个 cacheInfo.plist 档案文件,里面只存两组关键数据:

档案键内容作用
accesses每条缓存的最后访问时间供 LRU 排序
sizes每条缓存的磁盘大小计算总占用

初始化时会把所有sizes求和,得到实时磁盘用量_diskCacheUsage(见 diskCacheInfo 加载逻辑)。每个缓存文件本身则是用URL 的 MD5 哈希命名落盘的,规则见 cacheKeyForURL。

💡 小技巧:定义SDURLCACHE_DEBUG=1后,档案里还会额外记录每条缓存对应的原始 URL,方便调试(SDURLCache.h)。

核心揭秘:balanceDiskUsage 的三段式淘汰

当磁盘用量达到上限,balanceDiskUsage 方法执行完整的 LRU 淘汰,分三步走:

1️⃣ 先算"要腾多少空间"

capacityToSave = 当前磁盘用量 − diskCapacity

只要用量没超上限,方法会直接 return,零开销——这是它高效的第一层原因。

2️⃣ 按访问时间排序,最旧的排最前

方法把accesses档案按时间戳升序排序,得到一份"从最冷到最热"的淘汰候选队列。

3️⃣ 逐个删除直到腾够空间

从队列头部(最久未访问的条目)开始删,每删一个就从capacityToSave里扣掉它的大小,直到欠款清零为止。删除动作由 removeCachedResponseForCachedKeys 完成:删磁盘文件、清档案记录、扣减用量计数,三步一气呵成。

注意这里的批量删除设计:先收集所有待删 Key,再一次性执行,避免边遍历边删造成状态错乱。

谁来触发淘汰?5 秒一醒的维护定时器

SDURLCache 没有"每次写入都立刻清理",而是用一个 5 秒周期的 GCD 定时器做周期性维护(maintenanceTimer):

  • ⏰ 每 5 秒触发一次 periodicMaintenance
  • 用量超过上限 → 在独立磁盘 IO 队列上执行 LRU 淘汰
  • 没超上限但有脏数据 → 顺路把档案持久化到磁盘
  • 执行完先挂起自己,等有新的缓存写入时再被唤醒(见 storeRequestToDisk 中的恢复逻辑)

这套"休眠—唤醒"设计让空闲期的 App 几乎不产生任何磁盘 IO,非常省电。

细节亮点:LRU 访问时间的"延迟写入"

缓存命中时是更新访问时间的最佳时机,但每次都写 plist 太费 IO。SDURLCache 的做法很聪明(cachedResponseForRequest):

  • 命中磁盘缓存后,只在内存里更新访问时间,并打上"脏"标记
  • 把磁盘 IO 和档案保存留给维护线程批量完成
  • 命中的响应同时回填到内存缓存,下次访问更快

读写操作全部收敛到独立的磁盘队列串行执行,绝不阻塞主 Run Loop,这也是它敢叫"为速度而 Fork"的原因(README.md)。

写盘前的三道防护:垃圾数据根本不进库

淘汰机制再强,也不如"少存垃圾"有效。SDURLCache 在数据落盘前设置了层层闸门:

  1. 最小缓存间隔:默认 5 分钟内就要过期的响应直接不写盘,避免占着空间白过期(minCacheInterval 属性说明)
  2. 尊重服务器指令Cache-Control: no-storePragma: no-cache的响应一律拒收,过期时间解析逻辑见 expirationDateFromHeaders
  3. 单条体积上限:单条响应比整个diskCapacity还大?直接跳过,防止"一条缓存吃掉全部配额"(storeCachedResponse)

快速上手:三行代码开启磁盘缓存

SDURLCache *urlCache = [[SDURLCache alloc] initWithMemoryCapacity:1024*1024 diskCapacity:1024*1024*5 diskPath:[SDURLCache defaultCachePath]]; [NSURLCache setSharedURLCache:urlCache];

替换默认共享缓存后,App 立即拥有磁盘 HTTP 缓存能力,容量与淘汰策略完全由你掌控。更多 API(如isCached:removeAllCachedResponses)可在 SDURLCache.h 中查阅。

总结:一张图看懂容量守护全链路

新响应到达 → 三道防护过滤 → 异步写盘 → 用量+档案更新 ↓ 5秒维护定时器唤醒 → 用量 > diskCapacity? ↓ 是 LRU 排序 → 从最冷条目删起 → 腾够空间为止

SDURLCache 的设计哲学可以概括为一句话:用最少的 IO,换取最稳定的磁盘占用上限。理解它的 LRU 淘汰链路,对你在任何项目中设计缓存容量管理都会有直接启发。

【免费下载链接】SDURLCacheURLCache subclass with on-disk cache support on iPhone/iPad. Forked for speed!项目地址: https://gitcode.com/gh_mirrors/sdu/SDURLCache

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/27 14:51:36

悟空Agent实战:LLaMA-Factory高危0day漏洞挖掘与修复

前言 本次,我们将以53K Star的开源明星项目LLaMA-Factory为战场,详细展示悟空AI Agent如何在实际场景中,精准挖掘高危远程代码执行0day漏洞(CVE-2025-53002),并推动官方修复的技术实战。 一、LLaMA-Facto…

作者头像 李华
网站建设 2026/8/27 14:38:08

Jeff Dean押注AI4S:从分布式系统到科学发现的基础设施革命

谷歌内部最核心的工程人员 Jeff Dean 从谷歌离开,新公司的方向锁定 AI4S。这个消息一出来,很多人的第一反应是:谷歌的地基少了一个人,AI 赛道多了一个新变量。Jeff Dean 不是普通高管,他在过去二十年里直接参与了谷歌技…

作者头像 李华
网站建设 2026/8/27 14:37:14

IntelliJ IDEA快捷键

直接另起一行 shift 回车 自动补全 Ctrl shift 回车 单行注释 ctrl / 复制一行 ctrl d 删除一行 ctrl y 格式化代码 ctrl alt L 全局查找 ctrl shift F 改类名 shift F6 大小写转换 ctrl shift U 查找某个类 双击shift

作者头像 李华
网站建设 2026/8/27 14:35:46

【AI大模型】腾讯屠榜MTEB,嵌入模型告别BERT,拥抱LLM

前言 训练一个好的向量模型的重点在于最大限度地利用了更多、更高质量的负样本,来训练模型。腾讯提出的Conan-embedding,采用了动态硬负样本挖掘方法,以便在整个训练过程中向模型展示更多具有挑战性的负样本。最近发布Conan-embedding-V2版本…

作者头像 李华