发布于 2026-01-06 8 阅读
0

缓存策略 DEV 全球展示挑战赛,由 Mux 呈现:展示你的项目!

缓存策略

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

“计算机科学中只有两件难事:缓存失效和命名。”——菲尔·卡尔顿

缓存是一种用于临时存储数据的组件,以便更快地响应后续的数据请求。
这种临时存储方式可以缩短数据访问时间、降低延迟并提升 I/O 性能。

通用缓存策略
为了维护缓存,我们有一些策略,这些策略提供了维护缓存的指令。
最常见的策略如下:

  • 最少使用 (LFU):此策略使用计数器来跟踪条目的访问频率,并首先删除计数器最低的元素。
  • 最近最少使用 (LRU):在这种情况下,最近使用的项目总是位于缓存的顶部附近,当我们需要一些空间时,最近未访问过的元素将被删除。
  • 最近使用 (MRU):优先移除最近使用过的项目。我们将在较旧的项目访问频率更高的情况下使用此方法。

考虑缓存策略的最佳时机是在设计应用程序所需的每个模块时。
每次模块返回数据时,您都需要问自己几个问题:
我们返回的数据是否敏感且无法存储?
如果输入相同,返回的结果是否相同?我们
可以存储这些数据多久?
我们希望如何使缓存失效?
您可以在应用程序的任何位置添加缓存层。
例如,如果您使用 MySQL/MariaDB 作为数据存储,您可以启用并正确设置查询缓存。
这个简单的设置就能提升数据库的性能。
即使在编写代码时,您也需要考虑缓存。
您可以对对象和数据进行延迟加载,或者构建自定义缓存层来提高整体性能。
假设您正在从外部存储请求和处理数据,那么在同一次执行中,请求的数据可能会重复多次。
执行类似以下代码片段的操作可以减少对外部存储的调用次数:

<?php

class Cache
{
    protected $cache = [];
    public function getData($id)
    {
        if (empty($this->cache[$id])) {
            $externalData = $this->getExternalData($id);
            if ($externalData !== false) {
                $this->cache[$id] = $externalData;
            }
        }
        return $this->cache[$id];
    }
}
Enter fullscreen mode Exit fullscreen mode

在这段代码中,每次我们使用 ID 作为键标识符向外部存储发出请求时,都会将数据存储在 `$cache` 变量中。
下次当我们请求与之前 ID 相同的元素时,我们将直接从 `$cache` 获取元素,而无需再次从外部存储请求数据。

在 PHP 中,你可以使用最流行的缓存服务器,例如 memcached 和 Redis,它们都以键值对格式存储数据。
使用这些强大的工具可以显著提升应用程序的性能。

让我们使用 Redis 作为缓存存储来重建之前的示例。
在下面的代码片段中,我们假设您的环境中已安装了 Redis 库(例如 phpredis)并且 Redis 服务器正在运行:

<?php
 class Cache
{
    protected $cache = null;
    public function __construct()
    {
        $this->cache = new Redis();
        $this->cache->connect('127.0.0.1', 6379);
    }
    public function getData($id)
    {
        $externalData = $this->cache->get($id);
        if ($externalData === false) {
            $externalData = $this->getExternalData($id);
            if ($externalData !== false) {
                $this->cache->set($id, $externalData);
            }
        }
        return $externalData;
    }
}
Enter fullscreen mode Exit fullscreen mode

在这里,我们首先连接到 Redis 服务器,并调整了 `getData` 函数以使用我们新的 Redis 实例。
这个例子可以更复杂,例如,添加依赖注入并将 JSON 数据存储在缓存中,以及其他无数种可能性。
使用缓存引擎而不是自己构建缓存引擎的好处之一是,它们都提供了许多实用且强大的功能。
假设你只想将数据在缓存中保留 10 秒。使用 Redis 可以轻松实现这一点,只需将 `set` 调用更改为 `$this->cache->set($id, $externalData, 10)`,10 秒后,你的记录就会从缓存中清除。
比向缓存引擎添加数据更重要的是使已存储的数据失效或删除。
在某些情况下,使用旧数据没有问题,但在其他情况下,使用旧数据可能会导致问题。
如果你没有设置 TTL(生存时间)来使数据自动过期,请确保在需要时有办法删除或使数据失效。
作为开发人员,你不必局限于特定的缓存引擎。将其封装起来,创建一个抽象层,并使用该抽象层,这样您就可以随时更改底层引擎,而无需更改所有代码。

HTTP 缓存
策略使用一些 HTTP 标头来确定浏览器是否可以使用本地响应副本,还是需要从源服务器请求新的副本。
这种缓存策略在应用程序之外进行管理,因此您对其控制有限。
以下列出一些我们可以使用的 HTTP 标头:

  • 过期时间:此设置指定内容过期的未来时间。到达此时间点后,任何类似的请求都必须返回到源服务器。
  • 最后修改时间:此参数指定响应的最后修改时间。您可以将其用作自定义验证策略的一部分,以确保用户始终能够获取最新内容。
  • Etag:此标头标签是 HTTP 提供的用于验证 Web 缓存的几种机制之一,它允许客户端发出条件请求。Etag 是服务器分配给特定版本资源的标识符。如果资源发生更改,Etag 也会随之更改,从而使我们能够快速比较两个资源表示形式,以确定它们是否相同。
  • Pragma:这是一个旧的头部信息,源自 HTTP/1.0 实现。HTTP/1.1 缓存控制实现了相同的概念。
  • Cache-Control:此标头替代了 Expires 标头。它得到了良好的支持,并允许我们实现更灵活的缓存策略。此标头的不同值可以组合使用,以实现不同的缓存行为。

以下是可选项:

  • no-cache:这意味着在将任何缓存内容发送到客户端之前,必须在每次请求时重新验证该内容。
  • no-store:这表示内容不能以任何方式缓存。当响应包含敏感数据时,此选项非常有用。
  • 公开:这会将内容标记为公开,浏览器和任何中间缓存都可以缓存该内容。
  • 私有:此选项将内容标记为私有。用户的浏览器可以存储此内容,但中间方无法存储。
  • max-age:此参数设置内容缓存的最长时间,超过此时间内容必须重新验证。此选项值以秒为单位,最大值为 1 年(31,536,000 秒)。
  • s-maxage:这与 max-age 标头类似。唯一的区别是,此选项仅适用于中间缓存。
  • must-revalidate:此标签表示必须严格遵守 max-age、s-maxage 或 expires 标头所指示的规则。
  • proxy-revalidate:这与 s-maxage 类似,但仅适用于中间代理。
  • no-transform:此标头告诉缓存,在任何情况下都不允许修改接收到的内容。

静态文件缓存
一些静态元素非常适合缓存,其中包括以下这些:

  • 徽标和非自动生成的图像
  • 样式表
  • JavaScript 文件
  • 可下载内容
  • 任何媒体文件

这些元素通常不经常更改,因此可以缓存更长时间。
为了减轻服务器负载,您可以使用内容分发网络 (CDN),以便通过外部服务器提供这些不经常更改的文件。
基本上,CDN 有两种类型:

1 - 推送式 CDN:这种类型的 CDN 需要您手动推送要存储的文件。
您有责任确保上传到 CDN 的文件正确无误,并且推送的资源可用。
它主要用于上传图片,例如
用户头像。请注意,某些 CDN 在推送后可能会返回“OK”响应,但您的文件实际上尚未准备就绪。

2 - 拉取式 CDN:这是最简便的方法,您无需向 CDN 发送任何内容。
当请求通过 CDN 到达且文件不在 CDN 的存储中时,CDN 会从您的服务器获取资源并将其存储起来以供后续请求使用。
这种方式主要用于 CSS、图像和 JavaScript 资源。

一些知名的 CDN 服务商包括 CloudFlare、Amazon CloudFront 和 Fastly 等。
它们的共同点在于,它们在全球各地拥有多个数据中心,从而能够尽可能从距离您最近的服务器提供文件副本。
通过将 HTTP 与静态文件缓存策略相结合,您可以将服务器上的资源请求量降至最低。我们不会赘述其他缓存策略,例如页面
缓存。以上内容足以帮助您构建一个成功的应用程序。

文章来源:https://dev.to/mohamedahmed00/caching-strategy-7ia