多级缓存的设计与实现

在高并发的后端业务中,多级缓存是一种非常常见的设计。
事实上,多级缓存策略在计算机硬件中也普遍存在。

overview

为什么会有多级缓存?
通常缓存都比原数据要小。设立缓存的目的很简单:某些数据经常被访问,我们不想每次都去最深的地方(这里一般是指数据库)查找,所以会在更方便取到数据的地方把这些数据保存起来。

那么,为什么要用多级缓存呢?
对所有数据来说,访问频率并不一致。对于访问频率非常高的数据,我们称为热点数据。
例如,某个大 V 发了一条微博告诉大家他结婚了,那么这一条微博就是一个热点数据。热到不行时,我们的服务器平均每毫秒要访问这条数据一万次(不夸张……)。
我在上一篇文章里也提到过,分布式缓存 100us 的读取已经算是正常成绩了,但这个成绩完全不够支撑。我们必须有更快的缓存来保存这条数据,以减轻分布式缓存的压力。

对业务开发者来说,显式使用 CPU 的 L1、L2、L3 显然不现实。于是,我们只能指望主板上的内存条了。

现在的内存性能已经很强了,10000 mb/s 的读取速度也很普遍,至于延迟我还没有太清晰的概念。
既然内存这么强,我们就要尽量利用好它,所以内存通常会作为多级缓存的最顶层。

这篇文章中,我就尝试用 Java 来实现一下多级缓存。

各门语言的实现思路都大同小异。我这一年里基本都在写 Java,所以就直接用 Java 来写了。

Preconditions 预设计

对一个合格的后端服务来说,多级缓存的设计至少应包括以下几个功能:

  • 支持过期清理
  • 支持容量限制及逐出策略
  • 支持回源及回写机制(后面我会解释回源和回写这两个概念)

Back-to-Source 回源

通常说的回源,是指 CDN 层面上的回源:在这个 CDN 节点上没找到相关资源,就回到「源站」去获取该资源。
放到我们的缓存设计中,在缓存层面上,回源也是类似的意思:在这一层缓存中没找到这个数据,就到下一层「数据源」去获取资源。

Write-Back 回写

回写建立在回源的基础上。
当某一层缓存没找到资源时,就到下一层去找;如果找到了,这一层就把这个数据缓存起来。
这样下次再取这个数据的时候,就能马上取到了。

Code 搞起

简单写了一版,轻喷: https://github.com/XhinLiang/multi-level-cache

Share