上一篇 下一篇 分享链接 返回 返回顶部

美国站群服务器多站点缓存怎么分层:页面、对象与边缘缓存如何设置失效

发布人:Minchunlin 发布时间:12小时前 阅读量:13
美国站群服务器多站点缓存怎么分层:页面、对象与边缘缓存如何设置失效

先给出分层判断

美国站群服务器承载多个站点时,不应把所有请求放进同一个缓存池,也不应使用一个统一的失效时间。更稳妥的分层方式是:边缘缓存负责公开、可分发的响应;页面缓存负责匿名用户可复用的整页 HTML;对象与查询缓存负责应用内部可复用的数据。登录态、购物车、订单、后台和权限相关请求通常不进入页面及边缘缓存,只在必要时使用带有明确身份范围的对象缓存。

失效顺序也不能简单地“全部清空”。一次内容发布完成后,通常应先让对象或查询结果失效,再清理源站页面缓存,最后清理边缘对应的 URL、标签或路径。如果先清理边缘,而源站页面缓存仍是旧内容,边缘回源时可能重新获取旧页面,导致旧内容再次被缓存。这个顺序的成立条件是:源站已经完成数据提交,且页面生成逻辑能够读取到新数据。

多站点缓存首先要解决隔离问题

在同一台美国站群服务器上部署多个域名时,缓存键至少要包含站点标识。最直接的站点标识是完整主机名:

协议 + 主机名 + 路径 + 有效查询参数

例如下面两个地址即使路径相同,也不能共用同一份页面缓存:

https://site-a.example.com/news/1
https://site-b.example.com/news/1

如果缓存键只使用 /news/1,第二个站点可能读取第一个站点的 HTML。这不只是内容错误,还可能造成站点标题、链接、语言、品牌信息甚至权限边界混淆。

除了主机名,还要根据业务决定是否加入以下维度:

  • 语言、地区、货币:页面内容确实不同才加入;
  • 设备类型:只有移动端和桌面端返回不同 HTML 时才区分;
  • 登录状态或用户角色:通常不建议把这类页面放进公共页面缓存;
  • 查询参数:只保留真正影响页面结果的参数;
  • 版本或内容命名空间:用于批量发布和快速切换。

跟踪参数如 utm_source 是否从缓存键中移除,不能直接照搬。只有在确认应用完全不依赖这些参数,并且边缘规则已经经过验证时,才可以做归一化。page、sort、filter、lang、preview 等参数如果会改变响应内容,就不能被随意删除。

三层缓存的选择标准

层级适合缓存的内容主要缓存键主要失效方式不适合的内容
页面缓存匿名用户看到的完整 HTML站点、路径、有效查询参数、必要变体URL、标签、页面版本登录页、购物车、订单、后台
对象缓存文章、栏目、配置、权限范围内的可复用对象站点、对象类型、对象 ID、语言、版本单对象、标签、命名空间版本未区分身份的私密数据
查询缓存重复执行且结果可复用的查询结果站点、查询名称、规范化参数、权限范围关联对象变更、标签、版本强实时数据、权限依赖不明确的结果
边缘缓存静态文件和明确允许共享的公共响应域名、路径、有效参数、内容版本URL、前缀、标签、版本化文件名带会话和个人信息的响应

这里的“页面缓存”和“边缘缓存”可能同时存在。边缘缓存命中时,请求不会到达源站;边缘未命中后,才可能读取源站的页面缓存。两层同时启用时,必须分别定义 TTL 和失效动作,否则只清理一层并不能保证用户看到新内容。

页面缓存:只缓存可以被匿名用户共享的 HTML

页面缓存适合新闻详情页、公开产品页、公开栏目页、帮助文档等内容。判断一个页面能否缓存,可以先问三个问题:

  1. 不同用户访问时,页面主体是否相同?
  2. 页面是否依赖登录状态、购物车、订单或权限?
  3. 内容更新时,能否明确列出需要失效的 URL 或页面标签?

三个问题都得到肯定或可控的答案,才适合使用整页缓存。页面中如果只有少量用户相关区域,可以把公共页面缓存下来,再通过异步请求加载个人区域;不要因为页面中存在一个动态模块,就让整页缓存承载用户数据。

Nginx 源站页面缓存示例

下面是一个适用于 Linux、Nginx 反向代理场景的结构示例。它演示两个站点共用缓存区时,如何把 $host 放入缓存键,并绕过带身份或敏感路径的请求。缓存时间只是策略示例,应按发布频率调整。

events {}

http {
    proxy_cache_path /var/cache/nginx/site-pages
        keys_zone=site_pages:50m
        max_size=2g
        inactive=30m
        use_temp_path=off;

    map $request_method $skip_method {
        default 1;
        GET     0;
        HEAD    0;
    }

    map $http_authorization $skip_auth {
        default 1;
        ""      0;
    }

    map $http_cookie $skip_cookie {
        default 0;
        ~*(session|auth|token|cart|checkout|logged_in) 1;
    }

    map $uri $skip_uri {
        default 0;
        ~^/api/ 1;
        ~^/(admin|login|account|cart|checkout)(/|$) 1;
    }

    map $upstream_http_cache_control $skip_response_cache {
        default 0;
        ~*no-cache 1;
        ~*no-store 1;
        ~*private 1;
    }

    server {
        listen 80;
        server_name site-a.example.com site-b.example.com;

        location / {
            proxy_pass http://127.0.0.1:8080;

            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_cache site_pages;
            proxy_cache_methods GET HEAD;
            proxy_cache_key "$scheme|$host|$request_uri";

            proxy_cache_bypass
                $skip_method
                $skip_auth
                $skip_cookie
                $skip_uri;

            proxy_no_cache
                $skip_method
                $skip_auth
                $skip_cookie
                $skip_uri
                $skip_response_cache
                $upstream_http_set_cookie;

            proxy_cache_valid 200 5m;
            proxy_cache_valid 301 10m;
            proxy_cache_revalidate on;

            add_header X-Page-Cache $upstream_cache_status always;
        }
    }
}

这个配置有几个关键点:

  • $host 防止多个站点出现内容串站;
  • $request_uri 保留路径和查询字符串,避免不同分页或筛选结果共用页面;
  • Authorization、会话 Cookie 和敏感路径默认绕过;
  • 上游返回 Set-Cookie、private、no-store 或 no-cache 时不写入公共页面缓存;
  • X-Page-Cache 只用于排查,确认策略后可以移除,避免向外暴露内部状态。

修改 Nginx 配置前,应先备份实际修改的文件,并确认缓存目录由 Nginx 工作进程账号可写。适用于使用 systemd 管理 Nginx 的系统,可以按以下顺序检查:

backup="/etc/nginx/nginx.conf.bak.$(date +%F-%H%M%S)"
sudo cp -a /etc/nginx/nginx.conf "$backup"
printf '%s\n' "$backup"

sudo nginx -t
sudo systemctl reload nginx

如果检查失败,不要直接重启服务。应恢复刚才记录的备份文件,再次执行 sudo nginx -t,确认通过后再 reload。若站点使用独立的 conf.d 或 sites-enabled 文件,这些文件也要一并备份。

页面缓存的失效方式

页面缓存不应只依赖 TTL。TTL 适合兜底,不能代替发布时的主动失效。

  • 单篇文章更新:清理该文章 URL;
  • 栏目页更新:清理栏目页以及受影响的分页;
  • 首页聚合内容变化:清理首页和相关聚合页;
  • 模板或站点配置变化:按站点命名空间清理;
  • 全站结构调整:在确认影响范围后清理对应站点,不要默认清空所有站点。

如果缓存系统支持标签,可以给页面绑定站点、栏目、文章等标签。例如某篇文章同时影响详情页、栏目页和首页时,按文章标签或内容关系清理会比手工维护多个 URL 更可靠。标签机制不可用时,可以通过页面版本号或站点命名空间切换,让新请求使用新键,旧键等待自然过期。

对象缓存与查询缓存:提高应用复用率,不代替页面失效

对象缓存保存的是应用内部可以重复使用的数据,例如文章对象、栏目配置、站点设置、导航结构和公开的权限规则。查询缓存保存的是某个查询经过处理后的结果,例如某栏目下按时间排序的文章列表。

两者都比整页缓存更细,但失效关系也更复杂。一个文章对象更新后,文章详情页、栏目列表和首页推荐可能都受到影响。如果只删除文章对象,而不处理相关查询结果,页面仍可能读取到旧的列表。

建议使用带站点和版本的键

对象和查询缓存应有明确的命名空间,示例格式如下:

site:{site_id}:v{content_version}:object:{type}:{id}:{locale}
site:{site_id}:v{content_version}:query:{name}:{normalized_params_hash}

其中:

  • site_id 用于隔离不同站点;
  • content_version 用于批量发布或整体切换;
  • type 和 id 用于精确定位对象;
  • locale 只在多语言内容确实不同的时候使用;
  • normalized_params_hash 必须由规范化后的查询参数生成;
  • 如果结果受用户身份影响,还要加入明确的权限范围,或者直接禁止进入共享查询缓存。

查询参数的顺序不应导致同一查询生成多个无意义的键。例如 a=1&b=2 和 b=2&a=1 如果语义相同,就应在应用层统一排序后再生成键。但这类规范化必须由应用确认,不能在边缘随意改写。

对象和查询结果的失效方法

可以按照数据关系选择三种方式:

  1. 精确失效:只删除发生变化的对象键,适合单条记录变更。
  2. 标签失效:删除与某文章、栏目或站点相关的一组对象和查询结果,适合内容发布。
  3. 版本切换:提高站点或内容命名空间版本,让新请求自然使用新键,适合批量发布或需要快速回滚的场景。

TTL 仍然需要保留,但它主要用于防止异常数据长期存在。对于库存、订单状态、权限和支付结果等数据,不能因为设置了较短 TTL 就默认可以共享缓存,应根据业务一致性要求决定是否缓存。

对象缓存更新时,建议采用“先完成数据提交,再使旧对象失效”的顺序。若先删除缓存、后提交数据库,在并发请求下可能有请求读取旧数据并重新写回缓存。对于重要发布流程,还应让发布任务记录本次影响的对象、查询和页面范围,便于失败后重试,而不是依赖人工猜测。

边缘缓存:用响应头区分浏览器和共享缓存

边缘缓存通常位于用户与源站之间。它应根据响应是否可以被多个用户共享来决定是否缓存,而不是仅根据文件扩展名判断。

公开 HTML 可以使用共享缓存策略,但必须确认页面不含个人信息。一个示意性的公共 HTML 响应头如下:

Cache-Control: public, max-age=0, s-maxage=300, stale-while-revalidate=30

这里:

  • max-age=0 表示浏览器不长期直接使用该响应;
  • s-maxage 用于共享缓存,可与浏览器缓存策略区分;
  • stale-while-revalidate 表示在后台重新验证期间允许使用短暂旧响应;
  • 具体时间应根据内容更新频率、回源压力和可接受的旧内容范围调整。

带内容指纹的静态文件,例如文件名包含版本号或哈希值的 CSS、JavaScript、图片和字体,可以使用较长的浏览器缓存时间。文件内容一旦变化,就生成新文件名,而不是依赖逐层清理旧文件。没有版本化文件名的静态资源,不宜设置过长的不可变缓存时间。

边缘缓存必须遵守以下边界:

  • 响应含 Set-Cookie 时,除非已经明确设计了共享规则,否则不应缓存;
  • private、no-store、登录状态和个人订单页面不进入公共边缘缓存;
  • 同一路径在不同域名下内容不同,边缘缓存键必须包含域名;
  • 语言、货币、设备等差异必须通过明确的缓存键或响应变化规则表达;
  • 边缘规则与源站页面缓存规则不能互相覆盖,尤其要检查是否存在强制忽略 Cache-Control 的配置。

边缘失效通常有四种范围:

  • 单 URL:适合单页修改;
  • 路径或前缀:适合整栏目变更;
  • 标签:适合一个对象影响多个 URL;
  • 文件版本:适合带指纹的静态资源,通常通过发布新文件名处理。

不同边缘服务的清理接口、标签字段和传播行为并不相同,部署前应以实际服务文档为准。不能假定某个清理参数在所有边缘服务上都有效。

一次内容发布应如何清理三层缓存

以一篇公开文章更新为例,推荐流程如下:

  1. 完成内容提交,并确认源站直接访问已经能读取新数据。
  2. 使文章对象、栏目列表和相关查询结果失效,或切换对应内容版本。
  3. 清理源站页面缓存中的文章页、栏目页、首页聚合页等受影响 URL 或标签。
  4. 清理边缘层对应的 URL、路径或标签。
  5. 使用未登录请求检查页面正文、ETag、Last-Modified 和缓存状态。
  6. 记录清理范围和验证结果,失败时按原对象关系重试。

如果发生紧急回滚,应先让源站恢复到确定版本,再按相同顺序清理对象、页面和边缘缓存。不能只把数据库改回旧数据而保留新页面缓存,否则用户仍可能继续看到错误版本。

用请求头验证每一层是否按预期工作

验证时不要只看页面能否打开,而要确认到底是哪一层命中了缓存。可以使用不保存响应体的请求检查响应头:

curl -sS -D - -o /dev/null https://site-a.example.com/news/1
curl -sS -D - -o /dev/null https://site-b.example.com/news/1
curl -sS -D - -o /dev/null 'https://site-a.example.com/news/1?page=2'

重点观察:

  • 边缘服务提供的命中状态,例如 Age 或服务商定义的缓存头;
  • Nginx 示例中的 X-Page-Cache;
  • Cache-Control、ETag、Last-Modified 和 Vary;
  • 是否意外出现 Set-Cookie;
  • 不同域名访问相同路径时,响应主体和站点标识是否正确。

公开页面第一次请求出现 MISS、随后出现 HIT,通常说明页面缓存链路生效;但如果前面还有边缘层,源站的 Nginx 可能根本没有收到第二次请求。因此,边缘状态和源站状态要分别检查。

发布后,不能只验证首页。至少应覆盖:

  • 被修改的详情页;
  • 受影响的栏目页和分页;
  • 另一站点的同路径页面;
  • 带不同有效查询参数的页面;
  • 未登录请求与登录请求;
  • 静态资源新旧版本。

常见异常与处理顺序

发布后仍显示旧内容

先看边缘是否命中旧响应,再检查源站页面缓存,最后检查对象或查询缓存。如果边缘是旧的,清理边缘对应 URL;如果边缘未命中但源站页面仍旧,清理页面缓存;如果页面重新生成后仍旧,再检查对象键、内容版本和查询失效关系。

不同站点出现内容串站

应立即停止相关路径的公共缓存,清理可能受影响的站点缓存,然后检查缓存键是否包含 $host 或独立 site_id。同时检查边缘层是否把多个域名归到了同一个缓存规则中。此类问题不能通过缩短 TTL 解决,必须修正隔离维度。

页面始终无法命中缓存

常见原因包括请求带会话 Cookie、响应返回 Set-Cookie、上游返回 private 或 no-store、路径被绕过规则匹配,或者每次请求都携带不同且无效的查询参数。应先查看响应头和 Nginx 命中状态,再决定是否调整规则,不要直接删除所有绕过条件。

清理边缘后内容仍未更新

先直接检查源站是否已经是新内容,再确认清理对象是否包含完整域名、路径、查询参数或标签。若服务商的清理存在传播时间,应通过多个测试入口观察状态;在此期间不要反复执行全站清理,以免扩大影响范围。

适用边界:哪些内容不应进入公共页面或边缘缓存

以下内容通常应绕过公共页面缓存和边缘缓存:

  • 登录、注册、找回凭证和个人中心;
  • 购物车、订单、支付状态和账户余额;
  • 后台管理、内容预览和带编辑权限的页面;
  • 依赖用户角色、组织、合同或权限范围的响应;
  • 实时性要求高且旧数据可能造成业务错误的接口;
  • 包含个人信息、访问凭证或内部调试信息的响应。

这些页面仍然可以使用对象缓存或查询缓存,但键必须带有明确的用户、组织或权限范围,并且要评估权限变更后的失效延迟。无法清楚描述数据归属时,宁可不做共享缓存。

上线时只保留三条判定标准

在美国站群服务器上落地多站点缓存,可以用下面三条标准做最终检查:

  1. 隔离标准:缓存键和清理范围是否同时包含站点标识,且不会因域名、语言、权限或查询参数遗漏而串站。
  2. 分层标准:页面、对象、查询和边缘是否分别承担明确职责,动态和个人数据是否被绕过。
  3. 失效标准:一次发布是否能按“数据对象—源站页面—边缘响应”的顺序完成清理,并能通过响应头和页面内容验证结果。

满足这三条后,再根据内容更新频率调整 TTL。TTL 只能控制旧数据最多保留多久,不能替代正确的缓存键、发布顺序和主动失效机制。

目录结构
全文