响应缓存
当后续请求具有相同缓存 Key 时,响应缓存允许 AISIX 复用先前的非流式 Chat Completions 响应。这是网关侧响应缓存,不是模型服务提供方的提示词缓存,也不是控制面的配置快照缓存。如需为 Anthropic 模型配置模型服务提供方侧缓存,请参阅 Anthropic 提示词缓存。若要为相似而非完全相同的提示词返回缓存响应,可在策略上叠加语义缓存。
本指南介绍如何通过 AISIX Cloud Admin API 或声明式资源文件配置模型作用域缓存策略、验证缓存未命中和命中、选择共享范围、绕过与清空缓存条目,并按需使用 Redis 在多个网关实例间共享缓存响应。
响应缓存的工作原理
AISIX 会缓存完全匹配的非流式 Chat Completions 响应。流式响应和其他代理 API 类型不会使用此响应缓存路径。带生成 images 的响应(无论来自哪个上游)因体积原因不会写入缓存。
缓存策略可以应用于所有符合条件的请求、一个模型别名或一个调用方 API Key。每个策略把响应存储在网关的进程内 Memory 缓存中;如果启动时配置了 Redis,也可以存储在 Redis 中。
AISIX 缓存响应之前,网关必须能够使用所选后端,并且请求必须匹配一个已启用的缓存策略。
缓存 Key 匹配
AISIX 根据会影响上游响应的规范化 Chat Completions 请求创建缓存 Key。只有模型别名、消息角色和规范化内容、采样设置、响应长度以及额外的兼容 OpenAI 请求选项都相同时,两个请求才会共享缓存条目。
JSON 对象 Key 的顺序不会影响缓存匹配,包括嵌套对象中的 Key。数组顺序会影响匹配,因此工具定义相同但顺序不同的两个请求会使用不同缓存条目。
如果存在 temperature 和 top_p,则以 0.001 的精度比较,而不是按浮点数精确相等比较。因此,在其他所有字段都匹配时,位于同一千分位区间内的两个显式值会使用同一个缓存 Key。省略字段与显式设置该字段仍视为不同。
对于多目标模型,缓存 Key 使用调用方请求的别名,而不是处理未命中请求的目标模型。请求 ID 和请求头不参与缓存 Key。
调用方 API Key 是否分隔缓存由策略的 scope 字段控制。默认的 scope: api_key 下条目仅对写入它的 API Key 可见;scope: env 则在环境内所有调用方之间共享。见选择共享范围。
选择缓存后端
每个缓存策略都要选择匹配响应的存储位置:
| 后端 | 行为 |
|---|---|
| Memory | 默认。使用处理未命中请求的网关实例上的进程内缓存。 |
| Redis | 使用网关启动时配置的共享 Redis 缓存。 |
单实例部署或可以接受节点本地缓存条目时使用 Memory。多个网关实例需要共享同一策略的缓存响应时使用 Redis。AISIX 支持单个 Redis 端点、Redis Cluster 和 Redis Sentinel。
配置 Memory 缓存策略
以下示例使用默认的进程内 Memory 后端创建模型作用域策略。请选择控制面或开源配置路径,再使用通用验证步骤。如果已有其他已启用的缓存策略匹配示例请求,请先将其禁用或删除。
准备工作
开始前,请准备以下内容:
- 以下配置路径之一:
- AISIX Enterprise 或 AISIX Cloud,其中包含环境、已接入的网关和具有写权限范围的 Admin Token。对于 AISIX Enterprise,请按照 AISIX Enterprise 快速入门操作。如需申请 AISIX Cloud 访问权限,请联系 API7。
- 加载声明式
resources.yaml文件的开源 AISIX 网关。
- 可以发送非流式 Chat Completions 请求的模型别名和调用方 API Key。
curl。控制面路径还会使用jq。
导出 两种路径都会使用的网关连接和资源参数:
# AISIX_PROXY 不含尾部斜杠或 /v1 等端点路径
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="gpt-4o-mini"
export CACHE_PROMPT="cache-check-$(date +%s)"
AISIX Enterprise 或 AISIX Cloud
导出控制面连接参数:
# AISIX_CP 包含 /api,且不含尾部斜杠
# 本地 AISIX Enterprise 快速入门使用 http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CONTROL_PLANE_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
为示例模型别名创建 Memory 缓存策略。保存策略 ID,因为后面的 Redis 步骤会替换该策略:
CACHE_POLICY_RESPONSE=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/cache_policies" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"name": "default-chat-cache",
"enabled": true,
"backend": "memory",
"applies_to": "model:${AISIX_MODEL}",
"ttl_seconds": 3600
}
EOF
)
export CACHE_POLICY_ID=$(printf '%s' "$CACHE_POLICY_RESPONSE" | jq -r '.cache_policy.id')
printf '%s' "$CACHE_POLICY_RESPONSE" | jq
策略会自动投射到已接入的网关。响应包含策略 ID、环境 ID、所选后端、作用域、TTL 和时间戳。
如果 model: 选择器本身就是通配符模式,例如 model:openai/*,控制面会以 400 拒绝——调用方寻址的是该别名所承载的具体名称,而不是别名本身。环境中没有任何模型能应答的名称同样会被拒绝:只有当某个模型以该名称作为其 display_name,或某个通配符别名承载该名称时,这个名称才成立。
开源 AISIX 网关
在已定义示例模型和调用方 API Key 的资源文件中添加缓存策略:
cache_policies:
- name: default-chat-cache
enabled: true
backend: memory
applies_to: "model:gpt-4o-mini"
ttl_seconds: 3600
applies_to 中的模型名称是调用方在请求中使用的名称:对于具体配置的模型,即其 display_name;而当某个命名空间由 openai/* 这类通配符别名承载时,则是调用方在该命名空间下使用的具体名称(openai/gpt-4o),而不是别名模式本身。验证完整资源文件,然后重新加载网关。可运行的 Docker 工作流参见重新加载资源文件。
验证缓存未命中和命中
以下步骤读取 x-aisix-cache 响应头,网关只有在启动配置将 proxy.expose_debug_headers 设为 true 时才会发送它。请在用于测试的网关上开启该设置,或者按 x-aisix-request-id 找到每个请求的访问日志行,从其 cache_status 字段读取同样的判定结果。
定义一个每次都发送相同请求正文的辅助函数:
send_cache_request() {
curl -sSi -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"model": "${AISIX_MODEL}",
"messages": [{"role": "user", "content": "${CACHE_PROMPT}"}]
}
EOF
}
发送一次请求:
send_cache_request
第一个匹配请求应包含以下响应头:
x-aisix-cache: miss
未命中表示 AISIX 调用了上游模型服务提供方,并把响应写入缓存。在不更改模型或正文的情况下重复请求:
send_cache_request
重复请求应包含:
x-aisix-cache: hit
命中表示 AISIX 未调用上游模型服务提供方,直接返回了已存储的响应。在 AISIX Enterprise 和 AISIX Cloud 中,命中不产生费用,也不计入预算支出:其用量事件记录重放的 Token 计数和缓存节省计数,费用为 0。较早版本的控制面会对直连模型的命中按模型全价计费。
更改提示词,确认请求正文参与缓存 Key 的计算:
CACHE_PROMPT="${CACHE_PROMPT}-different" send_cache_request
更改后的请求应返回 x-aisix-cache: miss。
使用 Redis 共享缓存条目
Redis 允许多个网关实例共享条目。请确保 Redis 正在运行,且每个参与的网关都能访问它,然后把连接信息添加到 config.yaml:
cache:
redis:
mode: single
url: redis://127.0.0.1:6379/
添加 Redis 配置后,启动或重启每个网关。配置 backend: redis 的策略不会建立 Redis 连接。如果匹配策略选择 Redis,但未配置 cache.redis,AISIX 会禁用这些请求的缓存,而不会静默回退到 Memory。
启动时连不上 Redis 不会导致网关启动失败,但有界的启动连接尝试可能延迟所有监听器。尝试结束后,Redis 不再阻止监听器启动。代理监听器可用后,在 Redis 恢复应答之前,每条 backend: redis 缓存策略都按未命中处理。网关会输出一条 WARN 日志,其中包含后端、配置的端点值、原因和连接错误,并每 5 分钟重述一次。后台任务会在 Redis 恢复应答后立即接入缓存后端,此后 backend: redis 策略重新正常提供服务。
WARN 日志会原样包含配置的端点值:单机模式中的 url、集群模式中的 nodes,以及 Sentinel 模式中的 sentinels。嵌入这些值的所有凭据也会被记录。请使 用单独的 username 和 password 字段配置数据节点凭据。Sentinel 节点凭据仍会包含在 Sentinel URL 中,因此请限制对网关日志的访问。
Redis 明确应答并拒绝连接配置时走的是同一条降级路径,包括凭据被拒绝、服务端返回 NOAUTH 或 DENIED,以及服务端没有所配置的 database。此时告警带的是 reason=refused 而不是 reason=unreachable,后台重新接入的行为不变。无法在后台恢复的本地配置和解析错误会导致启动失败,包括:无法解析的 url;AISIX 无法读取或解析的 TLS 材料;仅配置客户端证书或密钥之一;缺少所选模式要求的字段;timeout_secs: 0;或主机名无法解析到任何地址。
cache.redis.username 和 cache.redis.password 在所有模式下都生效,且这些显式字段会覆盖内嵌在 url 中的凭据。凭据请作为一对设置,只设置其中一半会同时替换两半。cache.redis.database 在 single 和 sentinel 模式下生效;Redis Cluster 只有 DB 0。
是否支持向量检索是另一个问题,只有服务端真正应答探测时网关才会做出判定。没有得到应答的探测会在后台重试,因此启动时连不上的 Redis 并不会永久关闭语义匹配。参见使用 Redis 共享语义条目。
存储的响应会保留每个 choice 及其 logprobs。共享同一 Redis 的 1.7.0 及更早版本网关无法读取含有多个 choice 或 logprobs 的条目,会把它当作缓存错误处理。其他条目的写法与之前相同,因此混合版本的网关集群仍能正常共享它们。
Redis 可用后,通过前面使用的同一管理路径,用 Redis 策略替换 Memory 策略。
AISIX Enterprise 或 AISIX Cloud
现有控制面缓存策略的后端不能更改。请删除 Memory 策略,再创建使用 Redis 的替代策略,并保存新策略的 ID,以便后续更新和清空:
curl -sS -X DELETE \
"$AISIX_CP/environments/$ENV_ID/cache_policies/$CACHE_POLICY_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" | jq
CACHE_POLICY_RESPONSE=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/cache_policies" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF
{
"name": "shared-chat-cache",
"enabled": true,
"backend": "redis",
"applies_to": "model:${AISIX_MODEL}",
"ttl_seconds": 3600
}
EOF
)
export CACHE_POLICY_ID=$(printf '%s' "$CACHE_POLICY_RESPONSE" | jq -r '.cache_policy.id')
printf '%s' "$CACHE_POLICY_RESPONSE" | jq
开源 AISIX 网关
在 resources.yaml 中更改策略后端:
cache_policies:
- name: shared-chat-cache
enabled: true
backend: redis
applies_to: "model:gpt-4o-mini"
ttl_seconds: 3600
验证完整资源文件,然后重新加载网关,再测试 Redis 策 略。
验证 Redis 缓存行为
设置一个新的提示词,然后运行两次 send_cache_request。第一个请求应未命中,第二个请求应命中:
export CACHE_PROMPT="redis-cache-check-$(date +%s)"
send_cache_request
send_cache_request