前言:本篇文章翻译自 https://webspeedtools.com/what-is-caching/ ,非常详细地解释了不同缓存的区别,对大家选择缓存方案会有很大帮助。
网站缓存通常是唯一能在几秒钟内显著提升网站速度的手段。因此,了解什么是缓存对于优化网站速度将非常有帮助。
缓存有时会让人感觉难以理解,尤其是因为它有很多不同的用途。然而,它却是网站速度优化中无处不在的核心元素之一。
因此,我在这篇文章中简化了所有你需要了解的关于缓存的内容。我将以WordPress为例进行讲解,以便更好地理解。
什么是缓存
缓存是指将任何文件或数据的副本临时存储在一个或多个存储位置,以便在将来更快、更高效地传递这些文件。存储的副本可以是静态文件的完全相同的副本,也可以是动态文件在某个特定时间点的静态快照。
一个网页由图像、视频、HTML、CSS、JS、字体和其他类型的文件组成。因此,每次你使用Chrome、Safari、Firefox等网页浏览器访问网页时,浏览器都会下载网页所需的所有文件,然后将它们编译在一起,呈现出一个完整的网页。
这些文件类型分为两类,即静态文件和动态文件,在进行缓存时会分别考虑它们的处理方式。
静态文件缓存
如果同一个文件可以无需修改或重新创建就可以提供给所有人,那么该文件就可以称为静态文件。图像、视频、CSS、JS、字体等类型的文件通常被称为静态文件。例如,如果你的网站有一张图片,所有想要查看该图片的人都会看到相同的图片,而无需为任何人修改它。这些静态文件通常占网页的大头。
由于这些文件不会因用户而变化,缓存它们相对简单。因此,缓存这些文件只需将它们临时复制到一个或多个位置,当文件发生变化时再用更新后的文件替换即可。
动态文件缓存
如果一个文件需要根据用户特定的场景每次进行处理和生成,那么该文件可以称为动态文件或动态生成的文件。动态文件还可以包含根据用户互动或其他事件而变化的内容。HTML文件类型通常被视为动态文件。
例如,在浏览一个网站时,你可能会在网站的某个角落看到你的名字,但当其他人访问同一网站时,他们看到的则是他们的名字。正因为如此,这些网页需要在每次有不同用户访问时重新生成,这使得这些网页成为动态文件。
虽然HTML文件实际上是一种静态文件类型,但在现代网站中,它们根据用户特定的场景动态生成,因此被视为动态文件。例如,每当有访客请求WordPress网站的一个页面时,网络服务器会运行PHP脚本,然后从数据库中获取数据,最后生成HTML文件来响应访客的请求。
然而,即使每次有人发出请求时都会生成一个新的HTML文件,但对于特定页面来说,新生成的HTML文件可能与之前生成的HTML文件相同。在这种情况下,重新生成HTML文件将浪费服务器资源和宝贵的时间。事实上,过多的此类同时请求可能会占用大量服务器资源,最终可能导致服务器崩溃。
现在,通过缓存可以避免重复生成动态页面。当一个HTML页面动态创建后,你可以暂时存储或缓存该页面,然后在以后有人请求该页面时提供缓存的页面。
但由于动态文件会根据各种情况频繁变化,因此其缓存需要始终保持更新。这使得缓存动态文件变得相对复杂。这也是为什么大多数缓存挑战都集中在动态文件的缓存上,因此下面概述的大多数缓存基本原理都是为了解决这个问题。
例如,如果你使用内容管理系统(CMS)如WordPress来创建你的网站,那么你可能在该WordPress网站上创建了主页、About页面、Contact页面、博客文章以及其他类型的页面。现在,为了让人们查看这些页面,每个页面都需要有一个单独的HTML文件,提供给浏览器下载网页。
因此,你的WordPress网站应该为每个页面都生成单独的HTML文件。但是,如果你查看WordPress网站的文件结构,你会注意到它并未存储你网站各个页面的HTML文件。这是因为每当有人请求查看你WordPress网站的任意页面时,都会 为该页面创建一个新的HTML文件,然后提供给请求该页面的人。
这种HTML文件创建过程需要进行PHP处理、数据库查询和文件组装。因此,每次创建HTML页面时,服务器都需要进行一些计算,这些计算会占用服务器资源,并需要一些时间来完成。服务器需要为WordPress网站上的每个页面请求处理此过程。
因此,网站的流量越多,服务器使用的资源就越多。如果服务器资源不足以应对流量,那么服务器响应时间就会增加,最终服务器可能会崩溃。这就是为什么动态文件的缓存对于服务器稳定性和更快地向访问者交付网页至关重要的原因。
缓存类型
有许多种缓存类型,你可能会遇到其中一些。其中有些类型比其他类型更为常见。这里,我将讨论一些最常见的缓存类型,这些是你需要了解的,以便对这个主题有一个良好的理解。
对象缓存
对象缓存是指将数据库查询的结果临时存储起来,以便在将来更快、更高效地提供这些结果。这样,当有相同的查询请求时,可以更快地交付查询结果,因为结果已经存储在缓存中,不需要再次查询数据库来获取相同的结果。
在WordPress网站中,当有人想要访问一个页面时,该页面是动态生成的,这需要进行PHP处理并进行数据库查询来生成请求的页面。由于WordPress需要从数据库中获取数据,因此每个页面生成都需要执行多个数据库查询。这些查询中的每一个可能需要几毫秒的时间,这会占用你的服务器资源并延长页面生成的时间。
对象缓存可以在这里发挥作用,它通过存储这些查询的结果,使得当下次有相同的查询请求时,可以从缓存中提供结果,从而节省时间和计算资源。
默认的WordPress对象缓存
WordPress内置了一个称为WP_Object_Cache的对象缓存系统。该系统将数据库查询结果存储在PHP内存中,以避免对数据库的重复查询。然而,WP_Object_Cache是一种非持久性方法,因此缓存的数据只会在单个页面加载期间保留在内存中。
这在避免在同一页面请求中多次进行相同查询时非常有用。也就是说,如果在同一页面加载中多次出现相同的查询,缓存的数据将被重复使用,而不会再次查询数据库。不过,在页面加载完成后,缓存的数据将被丢弃,因此下次请求该页面时需要重新生成缓存。
因此,尽管这种方法可以通过避免在单个页面加载中重复进行相似的数据库查询来提高WordPress网站的性能,但它在跨多个页面加载时并不高效。这时,一个持久性缓存解决方案将会派上用场。
持久性对象缓存
持久性对象缓存允许你的网站充分利用对象缓存的潜力,使得被缓存的查询结果可以在未来的任何页面加载时从缓存中提供。
最受欢迎的两种持久性对象缓存解决方案是Redis和Memcached。尽管它们的用途相同,但Redis更受欢迎,并且比Memcached提供更多的好处。如果你想了解更多,可以查看Redis和Memcached的比较。
你也可以将其中任意一种与WordPress网站一起使用,以更快地交付查询结果,并减少服务器资源的使用。
当WordPress中启用了持久性对象缓存时,数据库查询结果会被缓存,因此类似查询的后续请求将从缓存中提供结果。然而,这并不能完全消除对数据库的查询,而是显著减少了总查询次数。
例如,在启用对象缓存后,要提供一个非常基础的网页,数据库查询次数可能会从22次减少到2次。这代表了最低的查询次数,实际情况下总查询次数通常会远高于22次。
根据你使用的主题、插件和其他设置等各种因素,数据库查询次数可能会超过100次。因此,对象缓存可以大幅节省服务器的计算资源,并加速网页的交付。
但即使如此,每次服务器收到页面请求时仍需进行一些数据库查询,并从头生成HTML页面。为了解决这种低效问题,你可以使用整页缓存。
整页缓存
整页缓存(也称为页面缓存)是指将动态生成的HTML页面的静态快照临时存储起来,以便在将来更快、更高效地交付这些页面。当HTML页面被缓存后,任何对此页面的请求都可以直接从缓存中提供,而无需再次动态生成页面。这减少了服务器资源的负载,并有助于加快网页的交付速度。
在WordPress中,像WP Rocket、WP Fastest Cache、W3 Total Cache、Swift Performance等整页缓存插件会缓存动态生成的HTML页面。这些应用级缓存插件通常将缓存的页面保存在WordPress的文件结构中。因此,如果你查看文件结构,可能会在那里找到以HTML文件格式保存的页面。
因此,提供这些缓存页面时,不需要进行任何数据库查询,甚至不需要运行PHP脚本来生成HTML文件。然而,为了提供缓存的页面,仍然需要执行一个名为advanced-cache.php的WordPress PHP脚本,该脚本会检查是否存在所请求页面的缓存文件。
因此,你的Web服务器仍然需要执行PHP脚本来提供缓存的页面。但你可以通过使用反向代理缓存来解决这种低效问题(将在本文的后面部分讨论)。
整页缓存分为两种类型:公共缓存和私有缓存。
公共缓存
公共缓存是一种整页缓存,它存储动态页面的快照,这些快照可以被所有人使用。因此,在公共缓存的情况下,所有访问者将看到相同的网页内容,而不考虑他们是谁。因此,适用于公共缓存的页面不能包含任何个性化内容,例如访客的姓名、购物车中的商品数量等。
有一种叫做微缓存的公共缓存,它用于在极短时间内缓存文件。
微缓存是一种公共缓存,用于在非常短的时间内(例如1秒)缓存HTML页面。这对于高流量且内容频繁变化的网站非常有用,如股票价格、体育比分、突发新闻等。
然而,如果一个网站流量很高但内容不频繁变化,那么使用常规的整页缓存会更有利,常规缓存的文件保存时间较长,如几周、几个月甚至几年。这种较长的缓存过期时间可以减轻服务器的负担,避免每秒钟不必要地创建一个页面,而实际上相同的页面可以使用更长的时间。
私有缓存
私有缓存是一种整页缓存,它存储特定于每个用户的动态页面快照。因此,在私有缓存中,同一个网页的不同版本会根据访问者的身份来交付。这些不同版本的页面通常因页面上的个性化信息或与用户相关的信息而有所不同。
例如,不同的信息可能包括已登录用户的姓名、用户的待审核评论、WordPress管理栏等。当实施私有缓存时,针对每个请求页面的用户(通常是已登录用户),都会存储该页面的不同缓存版本。这将占用大量的服务器存储空间,可能会抵消私有缓存带来的页面速度提升。
此外,由于私有缓存的特性,每当出现新的用户场景时,个性化页面都需要重新创建。因此,每当有新用户访问个性化页面时,该页面可能需要从头开始创建,然后缓存供该用户以后使用。因此,用户只有在再次访问页面时,才能感受到缓存带来的好处。因此,如果你的个性化网页不经常受到用户的重复访问,私有缓存的效果就不会很明显。
有一种方法可以将公共缓存用于包含个性化内容的网页,那就是使用AJAX,这种方法比使用私有缓存效率更高。
公共缓存用于个性化页面
在使用私有缓存时,你需要缓存多个版本的相同页面,这会占用大量的服务器存储空间。此外,如果对包含个性化内容的页面使用公共缓存,可能会导致缓存内容混乱,使得访客看到的内容是为其他人准备的,而不是他们自己的。
以 WordPress 为例,当访客请求查看一个网页时,页面是通过运行 PHP 脚本和查询 WordPress 数据库动态生成的,然后再将页面呈现给访客。
当启用整页缓存时,网页只会为第一次请求页面的访客(或在缓存被清除后的第一次用户)动态生成。然后,将动态生成的页面输出以 HTML 文件格式存储为缓存文件。因此,后续对相同页面的访问将从已有缓存中提供该文件。
这意味着,当提供缓存页面时,不再需要运行 PHP 脚本来创建 HTML 页面。因此,如果你的网页包含特定于用户的个性化内容(如用户的姓名、购物车中的商品数量等),则无法将这些用户特定的内容提供给每个用户。这是因为页面现在是从缓存内存中提供的,而不是为每个用户动态生成的。
因此,任何请求返回缓存页面的用户将看到的是第一个用户的内容,而不是请求页面的用户的内容。因此,如果使用公共缓存,提供个性化网页将会出现问题。
不过,你可以通过利用 AJAX 来克服这个问题。
AJAX(异步 JavaScript 和 XML) 是一种 JavaScript 技术,用于在无需重新加载页面的情况下,基于从 Web 服务器获取的数据更新网页的部分内容。AJAX 在浏览器的后台运行,与服务器进行通信,因此不会干扰页面的初始加载方式。
你可能在浏览电商网站时见过这种情况。当页面最初加载时,你看到的是一个空购物车,而过了一会儿,购物车突然显示出实际的商品数量。这是因为 AJAX 在收到来自服务器的信息后,更新了购物车的内容。
由于 AJAX 在浏览器后台运行,而不是在服务器上,它允许对个性化页面进行公共缓存。
让我们回到之前讨论的 WordPress 示例。在这个示例中,PHP 无法更改完全缓存页面的内容,这意味着公共缓存不适用于具有个性化内容的网页。
然而,你可以通过利用 AJAX 克服这个问题。与在服务器端运行的 PHP 不同,JavaScript 在客户端或浏览器中运行。因此,即使 PHP 无法修改缓存页面的内容,AJAX 可以做到这一点。因此,通过使用 AJAX,即使是具有个性化内容的页面,也可以利用公共缓存。
由于缓存页面无需为每个请求动态生成,它们显著节省了服务器资源。因此,AJAX 将通过允许你对个性化页面使用公共缓存,帮助减少服务器资源的使用。
相反,如果对个性化内容的页面使用了没有缓存或私有缓存的方法,那么这将消耗更多的服务器资源,无论是计算能力还是存储使用。
因此,将 AJAX 与缓存结合使用,还可以改善用户体验,使页面加载更快。
另外,还有一种缓存个性化页面并将其提供给用户的方法,那就是使用 Edge Side Includes(ESI),这一点将在本文稍后的 CDN 缓存部分中讨论。
我应该使用全页缓存还是对象缓存?
全页缓存相比对象缓存通常能提供更高效的结果。这是因为对象缓存仅缓存数据库查询的结果,所以每次新的页面请求时,网页仍需动态生成。但全页缓存则缓存了整个页面,因此新页面请求可以直接从缓存中提供,无需进行数据库查询或重新生成页面。
然而,并非所有网页都能高效地实现全页缓存。这是因为全页缓存会缓存整个网页,而不考虑网页是否需要为不同的用户单独生成。
例如,如果你的网站有登录用户,你可能希望通过在网页的头部显示用户的姓名来个性化网页。因此,网页的头部应该根据访问网页的用户显示不同的姓名。但如果使用全页缓存,这可能会成为问题。因为整个页面将被缓存,所以每个人都会看到缓存时用户的姓名,而不是他们自己的姓名。
如前所述,你可以使用私有缓存、AJAX 或 ESI 来解决这个问题。你需要选择最适合你特定网站需求的方案。
如果你的网站页面不适合全页缓存,或如果你的网站在很大程度上依赖于更快的数据库查询结果交付,那么你需要依赖对象缓存。对象缓存将缓存数据库查询结果,这有助于更快地交付这些查询结果,从而加速动态页面的生成。
此外,对象缓存不会对个性化页面的提供造成问题。因此,你可以使用它来处理各种类型的网站。不过,当然,它的性能提升不会像全页缓存那样显著。
如果你的网站只有公共页面或特定页面对每个访问者都是相同的,那么你可以无问题地使用全页公共缓存。在这种情况下,你甚至不需要对象缓存。但是,如果你的网站需要根据个别用户场景生成个性化页面,那么你可以使用对象缓存或根据具体情况考虑使用私有缓存、AJAX 或 ESI。
你还可以将对象缓存和全页缓存结合使用,以便你的网站能从中受益。例如,如果你的网站有公共页面和个性化页面,那么公共页面将从全页缓存中受益,而个性化页面将从对象缓存中受益。在这种设置中,你应注意仅对公共页面使用公共缓存,而不对任何个性化页面使用公共缓存。
需要注意的是,如果你使用的是 WordPress,那么你可能会发现许多缓存插件不支持私有缓存。这可能会导致缓存个性化页面时出现问题,或者根本不缓存个性化页面。因此,你需要谨慎选择适合你特定网站需求的优质缓存插件。
反向代理缓存
反向代理是一种作为你的网络服务器附加层的服务器,通过管理所有用户请求进出网络服务器来工作。它也被称为 Web 服务器加速器或 HTTP 加速器。
当用户请求一个网页时,反向代理服务器接收请求,然后将该请求转发给网络服务器。在网络服务器响应请求后,反向代理服务器接收响应,然后将响应转发给用户。
因此,反向代理缓存意味着暂时存储由网络服务器发送的响应文件的副本。所以,当有人在未来发出类似请求时,反向代理服务器可以通过从其缓存内存中提供网站文件来非常快速地响应请求,而无需与网络服务器进行交互。
对于 WordPress 网站来说,如果页面已被缓存到反向代理服务器中,则不需要 PHP 处理或数据库查询。
最受欢迎的反向代理之一是 Varnish。你还可以使用像 NGINX 的 FastCGI 缓存模块这样的服务器级全页缓存解决方案,以实现与使用反向代理缓存相同的缓存解决方案。实际上,它通常提供比 Varnish 更快的结果和更好的性能。
但如果你想要一个更好的解决方案,你可以查看 LiteSpeed 服务器,它提供了服务器级全页缓存,并且还提供了适用于 WordPress 和其他 CMS 平台的缓存插件,方便管理缓存配置。
虽然 NGINX 和 LiteSpeed 通常用作 Web 服务器应用程序,但它们也可以像 Varnish 一样用作反向代理服务器,位于 Apache、NGINX、LiteSpeed 等 Web 服务器之上。例如,你可以使用 LiteSpeed 服务器作为 Apache、NGINX 或另一个 LiteSpeed 服务器的反向代理。
在 WordPress 的情况下,应用级全页缓存插件如 WP Rocket、W3 Total Cache 等需要依赖 PHP 脚本来处理每个页面请求。这就是为什么即使是缓存页面也需要 PHP 进程。但服务器级全页缓存插件如 LiteSpeed Cache(需要使用 LiteSpeed 服务器)将从服务器存储和管理缓存页面。因此,提供缓存页面时不需要涉及任何 PHP 脚本或 WordPress。因此,服务器级全页缓存可以替代对反向代理缓存的需求。
CDN缓存
CDN(Content Delivery Network)缓存意味着将不同文件的副本临时存储在全球多个存储位置,以便更快地将这些文件传递给任何地理位置的用户。
CDN 提供商在全球范围内拥有许多数据中心。因此,如果一个文件已被缓存到 CDN 中,那么对该文件的任何请求都将从距离请求者最近的数据中心提供。由于文件需要传输的距离更短,因此可以更快地将文件传递给用户。这就是为什么使用 CDN 缓存可以显著减少任何网站的加载时间。
如果你想了解 CDN 如何影响仅有本地访问者的网站,可以查看这篇关于本地网站使用 CDN 的文章。
要使用 CDN 缓存你的网站文件,你需要使用 AWS CloudFront、Google Cloud CDN 等 CDN 提供商。然后,你的网站文件需要通过推送或拉取等方法从你的网络服务器或存储位置缓存到 CDN 提供商的数据中心。随后,可以通过 CDN 提供商提供的一个子域名来访问这些文件。
因此,一旦文件被缓存到 CDN 中,使用该子域名对文件的任何请求都将从 CDN 提供商的数据中心提供。你还可以将你自己的子域名作为替代域名(也称为 CNAME)指向他们提供的子域名。这样,这些缓存的文件也可以从你的子域名访问。
CDN 缓存主要用于静态文件,如图片、视频、CSS、JS 等。它也用于静态 HTML 文件,即相同的 HTML 文件可以传递给任何请求相同网页的用户。
CDN 缓存也可以作为动态生成的 HTML 文件的静态快照,比如在 WordPress 网站中。但这主要是由反向代理 CDN 提供商提供的功能。
反向代理 CDN
反向代理 CDN 是一种充当反向代理的 CDN 类型,类似于之前讨论的反向代理缓存。这意味着反向代理 CDN 将作为你 Web 服务器的附加层,处理所有传入和传出的流量。
如果你使用传统 CDN,则需要使用 CDN 提供商的子域名(或替代域名)来传递你的网站文件。但当使用反向代理 CDN 时,你无需使用 CDN 提供商的任何子域名。相反,所有文件都将从你的主域名缓存并提供。
当然,如果你愿意,仍然可以选择使用一个子域名来提供静态文件。实际上,如果你不希望使用反向代理 CDN 提供商来提供这些静态文件,则可以选择使用传统 CDN 提供商来完成这项工作。
使用反向代理 CDN 需要更改你的域名的NameServer记录,将其指向 CDN 提供商提供的NameServer。完成此操作后,你的所有网站流量将由 CDN 提供商处理,正如之前关于反向代理缓存部分中讨论的那样。
因此,反向代理 CDN 将代表你的 Web 服务器接收用户请求,然后将该请求转发到你的 Web 服务器。而在 Web 服务器响应请求后,反向代理 CDN 将接收响应并将其转发给用户。相应地,在收到 Web 服务器的响应后,反向代理 CDN 可以缓存该响应以供将来使用。因此,反向代理 CDN 可以消除之前讨论的反向代理缓存的需求。
如果某个网页在 CDN 服务器上被完全缓存(包括 HTML 文件和其他静态文件),那么对该网页的任何请求都无需再访问 Web 服务器。这不仅可以减少服务器的负载,同时还可以提高网站的速度。
Edge Side Includes (ESI)
ESI是一种标记语言,允许将动态网页的部分内容视为独立的片段,这些片段可以分别处理,然后组合在一起形成一个完整的页面。
通过这种方式,任何动态网页都可以分片段缓存。因此,如果一个网页包含对所有人相同的公共内容和对个别用户唯一的个性化内容,那么ESI将允许分别缓存这些公共部分和个性化部分。然后,这些独立的部分可以组合在一起形成一个完整的页面。
换句话说,ESI 允许你缓存整个网页,同时在其中保留一些空白,这些空白部分可以用不同的内容填充以形成完整的页面。这里的空白部分可以代表个性化内容,而页面的其余部分则是公共内容。
因此,通过使用ESI,我们可以在不实际使用整页缓存的情况下提供完整的网页。这有助于克服整页缓存的一个问题,即页面要么完全缓存,要么根本不缓存。因此,对于需要根据个人用户场景进行个性化的网页,使用ESI相比私有缓存会更加高效,因为私有缓存需要大量存储空间来缓存相同的网页。
ESI处理是在CDN边缘(位于不同地理位置的数据中心,负责向网站访客交付内容)进行的。当HTML页面中包含ESI标签时,CDN边缘会尝试通过使用已缓存的匹配内容或向网络服务器发出请求来获取用于解析这些标签的内容。
因此,一旦所有ESI标签都被解析,整个页面就完成了组装,CDN才会开始向访客传递页面。因此,页面中包含的ESI标签越多,页面的组装和传递所需的时间就越长。
由于解析ESI标签的过程会延迟网页的传递,初始服务器响应时间和TTFB(Time to First Bite)都会增加,这会让网站访客感觉到网站加载速度变慢。
相反,当我们使用AJAX时(本文前面已经讨论过),AJAX可以作为ESI的替代方案来缓存个性化页面,这样对访客来说,网站加载速度看起来会更快。这是因为在开始传递网页之前不需要进行任何组装。相反,AJAX通过在浏览器后台运行JavaScript来更新页面内容。
这也是为什么当你使用ESI而不是AJAX时,你会看到购物车中的商品数量正常加载,而不是像使用AJAX那样在加载完空购物车后突然更新。
如果你的网站包含一些频繁更改的内容,并且这些内容出现在你网站的许多页面中,那么ESI可以大大提高网站性能。例如,在你的WordPress网站的侧边栏中显示的“最近文章”小部件。每当你撰写新文章时,该小部件都需要更新。因此,所有包含该小部件的页面也需要更新。
现在,如果你使用整页缓存,那么所有包含该小部件的页面的缓存都需要清除并重新生成。这是因为整页缓存不能分片段缓存网页。但如果你使用ESI,那么缓存只需清除和重新生成一次“最近文章”小部件的内容。这也有助于减少服务器负载,因为CDN边缘只需向网络服务器发出一次请求以获取更新的内容。
然后,新缓存版本将用于“最近文章”小部件,而不是旧缓存版本。因此,更新的小部件将反映在所有网页中,而无需重新生成页面。
因此,不必仅仅因为添加了新文章就清除你网站上所有页面的缓存。在这种情况下,使用 ESI 的好处就会非常明显。
然而,每次有人请求包含该小部件的页面时,仍然需要在传递页面之前将小部件和页面的其余部分组合在一起。但在整页缓存中,页面一旦缓存,就不需要再进行组合。
尽管ESI可以帮助你的网站快速交付个性化页面,但它并不是一种官方认可的技术。因此,你会发现它的采用率至今仍然有限。
浏览器缓存
浏览器缓存是指在访问者的浏览器(如Chrome、Safari、Firefox等)中临时存储网站的不同文件副本。浏览器会将这些文件保存在访问者用于浏览网页的设备中。因此,当网页的文件已被保存到浏览器中,之后再次访问该页面时,就不需要重新下载这些已存储的文件。因此,浏览器只需下载自上次访问以来更新过的文件或未缓存的文件。
除了浏览器缓存之外,上述所有缓存方法都是服务器端缓存,因此它们要么将缓存文件存储在网络服务器中,要么存储在CDN数据中心。因此,每次有人访问网页时,都需要下载这些文件。但在浏览器缓存的情况下,缓存文件存储在访问者的浏览器中,因此一旦文件被缓存,就不需要再次下载。这就是为什么与其他缓存方法相比,浏览器缓存可以使网页加载速度非常快的原因。如果网站访问者的互联网连接速度较慢,这种性能差异会更加明显。
然而,浏览器缓存只对用户的重复访问有益,因为他们首先需要访问你的网站,才能让他们的浏览器缓存你的网站文件。
在配置网站文件的缓存时,你需要特别注意浏览器缓存。因为在更新网站上的内容后,你可以轻松清除服务器端缓存配置的缓存,但浏览器缓存却不是这样。一旦文件被缓存到访问者的浏览器中,你将难以控制这些文件。
因此,如果你的网站文件在浏览器中缓存了很长时间,那么你对网页所做的任何更新可能不会被浏览器下载,访问者将继续看到过时的内容。这就是为什么为了确保你的访客看到的是最新内容而非过时内容,你在设置缓存到期时间(也称为生存时间TTL)时需要格外小心,本文稍后会对此进行讨论。
DNS 缓存
域名系统(Domain Name System,简称 DNS)是将域名与 IP 地址链接起来的过程。Web 浏览器需要 IP 地址来查找托管特定域名网站的服务器。因此,当你在 Web 浏览器中输入一个域名后,浏览器首先会找到与该域名关联的 IP 地址,然后连接到该 IP 地址上的 Web 服务器,以获取你想访问的网站。
在从域名获取 IP 地址的过程中,会使用多种类型的 DNS 服务器。而这个通过服务器逐一查找的过程是比较耗时的。因此,在找到域名对应的 IP 地址后,可以将其临时保存在一种称为递归 DNS 服务器的服务器类型中,并且也可以保存在访问者的 Web 浏览器中,以加快未来对同一站点的访问。这样,DNS 缓存在服务器级别和浏览器级别都得以实现。
为了在你的网站上利用 DNS 缓存,你需要为 DNS 记录设置合适的生存时间(TTL)。你的 DNS 服务器提供商会为你提供设置 TTL 的选项。根据你的实际情况,你的 DNS 服务器提供商可能与网络托管服务提供商相同,可能是域名注册商,第三方提供商,或者是你自己创建的私人NameServer。
如果你有兴趣了解更多相关内容,可以查看这篇关于 DNS 服务器及其如何影响网站速度的文章。
缓存管理
现在你已经了解了各种不同类型的缓存及其如何为你带来优势,但还有一个重要的部分,那就是如何管理这些缓存。这一点至关重要,以确保你的网站访问者在网页更新后不会看到过时的内容。
生存时间 (TTL)
生存时间(Time to Live,TTL)指的是数据或文件在缓存中保存的时间期限,过了这个时间期限后,这些数据或文件就需要被移除或刷新。换句话说,TTL 就是缓存的过期时间。
当你更新网站页面或其内容时,相应的缓存文件就会变得陈旧或过时。因此,你需要一个系统来移除这些缓存文件,以便访问者能够从你的网站获取最新的内容。TTL 就是这样一个系统的一部分,它有助于在文件达到一定时间后丢弃缓存文件。
你可以使用一种叫做 Cache-Control HTTP 标头的方法来声明任何文件的 TTL 时间。这用于指定文件是否应该被缓存,以及如果缓存的话,应该缓存多长时间。
TTL 时间长的文件将在缓存中保留的时间比 TTL 时间短的文件更长。
一般来说,静态文件更新不频繁,因此它们可以拥有较长的 TTL 时间。相反,动态文件如 HTML 页面则经常变化,缓存它们可能会导致访问者看到过时的内容。因此,如果你选择缓存动态文件,那么它们应当具有较短的 TTL 时间。
不过,你只能为从你服务器提供的文件设置 TTL。如果你的网站使用了外部托管的文件,你将无法定义这些文件应该缓存多长时间。如果你有兴趣了解更多关于外部托管文件的内容,可以查阅这篇关于外部文件链接如何影响网站速度的文章。
在 CDN 缓存的情况下,你会遇到两种不同类型的 TTL。一种是边缘缓存 TTL (Edge Cache TTL),另一种是浏览器缓存 TTL (Browser Cache TTL)。边缘缓存 TTL 定义了网站文件在 CDN 数据中心中保存为缓存的时间。而浏览器缓存 TTL 定义了文件在访问者浏览器中保存为缓存的时间。
缓存更新过程
当你将所有不同类型的缓存结合使用时,最终会形成一个多阶段的缓存过程。因此,每当你需要清除任何缓存文件时,必须清除所有相关阶段的缓存。这就是为什么你需要一个简单的流程,能够轻松地从这些不同的缓存阶段中清除缓存。否则,你可能会遇到这样的问题:尽管你已经清除了更新文件的缓存,但由于忘记清除缓存配置中另一个阶段的缓存,访问者仍然会看到过时的内容。
通常,你可以手动清除缓存过程中的不同阶段的缓存。但一个更好的解决方案是设置一个自动化的流程,自动为你清除缓存。这样,当你的网站进行任何更新时,系统会自动触发一个动作,移除所有与该更新相关的文件缓存。
如果你使用的是 WordPress,你可以找到许多缓存插件,帮助你实现针对特定缓存设置的缓存自动化过程。例如,LiteSpeed Cache、WP Rocket 以及其他一些缓存插件,能够通过自动化大部分与缓存相关的活动,确保你的缓存文件保持最新状态。