什么是三级缓存架构?请描述内存缓存、磁盘缓存和网络缓存的协作流程

解读

面试官问“三级缓存架构”并不是想听“L1/L2/L3”这种芯片级概念,而是考察你对移动端“数据加载性能与用户体验”这一核心场景的系统化思考。国内 App 日活高、网络复杂(弱网、高时延、省流量)、机型碎片,任何一次多余请求都可能带来耗电、卡顿、投诉。因此,能否用“内存-磁盘-网络”三级缓存把“最快命中、最少请求、最小流量”做到极致,是衡量候选人是否具备“工程化落地能力”的关键。回答时要突出三点:

  1. 每一级的数据结构、生命周期与淘汰策略;
  2. 读/写两条时间链的完整协作流程;
  3. 异常与一致性兜底方案(磁盘坏块、网络 304、CDN 回源失败等)。

知识点

  1. 内存缓存(Memory Cache)

    • 实现:LruCache / LinkedHashMap + 强引用 + 同步锁;图片场景用 AndroidX Collection 的 LruCache,Object 场景可自定义 SizeOf 逻辑。
    • 容量:Runtime.maxMemory() 的 1/8 是官方推荐,国内 4 G 小内存机型可动态下探到 1/16。
    • 淘汰:LRU + 引用队列弱引用兜底;onLowMemory() / onTrimMemory() 主动释放。
  2. 磁盘缓存(Disk Cache)

    • 实现:DiskLruCache(JakeWharton 版)或 OKIO 自己写 FIFO/LRU;国内 ROM 管控严,必须放 Context.getCacheDir(),勿用外置存储。
    • 容量:10~50 MB 区间,按可用空间比例(getUsableSpace())动态调整;老机型 sdcard 与内部存储合并场景要留 200 MB 安全垫。
    • 索引:以 URL 的 MD5 作为文件名,避免中文与特殊字符;header 中 etag/lastModified 存到同目录 *.meta,用于网络层做 304 校验。
  3. 网络缓存(Network Cache)

    • 实现:HTTP 协议缓存(Cache-Control、ETag、Last-Modified);国内厂商 CDN 普遍支持 Range 与 304,注意“微信/QQ 分享”场景下 CDN 回源带短链签名,容易把 302 当成新资源。
    • 离线:可配合 WorkManager 做“后台预拉”与“差分更新”,把热点资源提前放进磁盘缓存,降低高峰并发。
  4. 协作流程(读链)
    ① UI 线程发起数据请求;
    ② 内存缓存同步命中?直接返回主线程并终止;
    ③ 未命中则开子线程进磁盘缓存,命中后解码→写回内存→返回主线程;
    ④ 磁盘也未命中,走网络下载→写入磁盘→写入内存→返回主线程;
    ⑤ 网络 304 场景,把磁盘文件时间戳更新后直接当成新数据使用,避免二次解码。

  5. 协作流程(写链)
    ① 网络层收到 200 新数据,先写临时文件(*.tmp),校验 Content-Length 与 MD5 防 CDN 劫持;
    ② 校验通过 rename 到目标文件,同时把 etag/lastModified 写 *.meta;
    ③ 把文件解码后插到内存缓存,若内存超限触发 LRU 淘汰,仅清内存不清磁盘;
    ④ 发送 LocalBroadcast 或 EventBus 通知 UI 刷新,避免重复加载。

  6. 一致性 & 异常

    • 磁盘损坏:catch IOException 后自动删除脏文件,降级到网络;
    • 内存同步:使用原子引用 + CopyOnWrite 防止解码过程中被回收;
    • 多进程:图片浏览器/推送弹窗场景可能出现多进程,磁盘缓存必须加文件锁(FileLock)或使用 ContentProvider 封装;
    • 权限:Android 11 分区存储,磁盘缓存只能在内置目录,getExternalCacheDir() 需要 MEDIA_ACCESS 权限,面试时主动提“不会违规写外置”。

答案

三级缓存架构是指“内存缓存—磁盘缓存—网络缓存”由近到远的三层数据容器,其核心目标是“用最快路径命中、用最少流量更新”。
读数据时,先在当前线程查 LruCache,命中即返回;未命中则开线程进 DiskLruCache,命中后解码并回写内存,再返回主线程;磁盘也未命中才走网络,下载完成后先写磁盘、再写内存,最后返回。
写数据时,网络层收到新资源先做完整性校验,确认无误后落盘并更新索引,再把解码对象插到内存;若内存超限按 LRU 淘汰,磁盘与网络层不受影响。
通过 HTTP 304 与本地索引比对,可保证“磁盘不重复下载、内存不重复解码”,在弱网、省流、高并发场景下把流量节省 30% 以上,把图片加载耗时控制在 50 ms 内,从而满足国内 16 ms 帧率与 2 G 网络并存的现实环境。

拓展思考

  1. 折叠屏/多窗口场景下内存缓存容量是否需要动态翻倍?如何与 onConfigurationChanged() 联动?
  2. 国内厂商后台清理激进,DiskLruCache 被系统一键清除后,如何结合 WorkManager 做“断点续拉”与“差分更新”?
  3. 隐私合规趋严,磁盘缓存里可能残留用户头像或证件照,如何在上传成功后立即物理擦除(RandomAccessFile 写 0)并通过 SecurityProvider 做取证不可恢复?
  4. 直播电商秒杀场景,瞬间千万级并发,三级缓存如何与 CDN 预热、HTTP/3 QUIC、边缘函数(Edge Function)协同,做到“单 URL 单节点 1 秒 5 万次请求”不击穿?