

# 了解缓存键
<a name="understanding-the-cache-key"></a>

*缓存键* 确定发送到 CloudFront 边缘站点的查看器请求是否导致*缓存命中*。缓存键是缓存中对象的唯一标识符。缓存中的每个对象都有一个唯一的缓存键。

如果查看器请求生成与先前请求相同的缓存键，并且该缓存键的对象位于边缘站点的缓存中且有效，则会发生缓存命中。当存在缓存命中时，请求的对象将从 CloudFront 边缘站点提供给查看器，这具有以下好处：
+ 减少了源服务器上的负载
+ 缩短了查看器的延迟

*缓存命中率*越高（当查看器请求比例较高时，会发生缓存命中），网站或应用程序的性能就越佳。提高缓存命中率的一种方法是仅在缓存键中包含最少的必要值。有关更多信息，请参阅以下部分。

您可以使用[缓存策略](controlling-the-cache-key.md)修改缓存键中的值（URL 查询字符串、HTTP 标头和 Cookie）。（您也可以在查看器请求上使用 [Lambda@Edgefunction](lambda-at-the-edge.md) 或 [CloudFront Functions](cloudfront-functions.md) 来修改缓存键。） 在修改缓存键之前，请务必了解应用程序的设计方式以及它何时以及如何根据查看器请求的特征提供不同的响应。当查看器请求中的某个值确定源返回的响应时，您应在缓存键中包含该值。但是，如果您在缓存键中包含的值不会影响源返回的响应，则可能最终会缓存重复的对象。

## 默认缓存键
<a name="cache-key-default"></a>

默认情况下，CloudFront 分配的缓存键包括以下信息：
+ CloudFront 分配的域名（例如，d111111abcdef8.cloudfront.net）
+ 请求的对象的 URL 路径（例如 `/content/stories/example-story.html`）

**注意**  
`OPTIONS` 方法包含在 `OPTIONS` 请求的缓存键中。这意味着 `OPTIONS` 请求的响应将与 `GET` 和 `HEAD` 请求的响应单独缓存。

默认情况下，查看器请求中的其他值不会包含在缓存键中。请考虑来自 Web 浏览器的以下 HTTP 请求。

```
            GET /content/stories/example-story.html?ref=0123abc&split-pages=false HTTP/1.1
            Host: d111111abcdef8.cloudfront.net
            User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/68.0
            Accept: text/html,*/*
            Accept-Language: en-US,en
            Cookie: session_id=01234abcd
            Referer: https://news.example.com/
```

当与此示例类似的查看器请求到达 CloudFront 边缘站点时，CloudFront 将使用缓存键来确定是否存在缓存命中。默认情况下，缓存键中仅包含请求的以下组件：`/content/stories/example-story.html` 和 `d111111abcdef8.cloudfront.net`。如果请求的对象不在缓存中（缓存未命中），则 CloudFront 会向源发送请求以获取该对象。获取该对象后，CloudFront 会将它返回到查看器并将它存储在边缘站点的缓存中。

当 CloudFront 收到由缓存键确定的同一对象的另一个请求时，CloudFront 会立即将缓存对象提供给查看器，而不会向源发送请求。例如，请考虑以下 HTTP 请求，该请求在上一个请求之后到达。

```
            GET /content/stories/example-story.html?ref=xyz987&split-pages=true HTTP/1.1
            Host: d111111abcdef8.cloudfront.net
            User-Agent: Mozilla/5.0 AppleWebKit/537.36 Chrome/83.0.4103.116
            Accept: text/html,*/*
            Accept-Language: en-US,en
            Cookie: session_id=wxyz9876
            Referer: https://rss.news.example.net/
```

虽然该请求与上一个请求都对应于相同的对象，但它与上一个请求不同。它具有不同的 URL 查询字符串、`User-Agent` 和 `Referer` 标头，以及不同的 `session_id` Cookie。但默认情况下，所有这些值都不是缓存键的一部分，因此第二个请求会导致发生缓存命中。

## 自定义缓存键
<a name="cache-key-custom"></a>

在某些情况下，即使这样做可能会导致更少的缓存命中，您仍可能希望在缓存键中包含更多信息。您可以使用[缓存策略](controlling-the-cache-key.md)指定要包含在缓存键中的内容。

例如，如果您的源服务器使用查看器请求中的 `Accept-Language` HTTP 标头来根据查看器的语言返回不同的内容，则您可能希望在缓存键中包含此标头。在执行该操作时，CloudFront 会使用此标头确定缓存命中，并在*源请求*（当缓存未命中时，CloudFront 发送到源的请求）中包含标头。

在缓存键中包含其他值的一个潜在后果是，由于查看器请求中可能发生的变化，CloudFront 最终可能会缓存重复的对象。例如，查看器可能会为 `Accept-Language` 标头发送以下任意值：
+ `en-US,en`
+ `en,en-US`
+ `en-US, en`
+ `en-US`

所有这些不同的值都表明查看器的语言是英语，但变体可能会导致 CloudFront 将同一个对象缓存多次。这会减少缓存命中数并增加源请求的数量。您可以避免此重复情况，方法是不在缓存键中包含 `Accept-Language` 标头，而是将您的网站或应用程序配置为将不同的 URL 用于不同语言的内容（例如 `/en-US/content/stories/example-story.html`）。

对于要包含在缓存键中的任何给定值，您应确保了解查看器请求中可能会出现的不同变体的数量。对于某些请求值，将它们包含在缓存键中几乎没有意义。例如，`User-Agent` 标头可以有数千个唯一变体，因此通常不适合将它作为包含在缓存键中的候选项。也不适合将具有用户特定的值或会话特定的值并且在数千个（甚至数百万个）请求中唯一的 Cookie 作为包含在缓存键中的候选项。如果您确实在缓存键中包含这些值，则每个唯一变体都会导致缓存中存在对象的另一个副本。如果对象的这些副本都不是唯一的，或者如果您最终获得了大量略微不同的对象，而每个对象只获得少量的缓存命中，则可能需要考虑另一种方法。您可以从缓存键中排除这些高度可变的值，也可以将对象标记为不可缓存。

在自定义缓存键时，请保持谨慎。有时这样做是可取的，但可能会产生意想不到的后果，例如缓存重复的对象、降低缓存命中率以及增加源请求的数量。如果您的源网站或应用程序需要接收来自查看器请求的特定值以进行分析、遥测或实现其他目的，但这些值不会更改源返回的对象，请使用[源请求策略](controlling-origin-requests.md)在源请求中包含这些值，但*不* 将它们包含在缓存键中。