应使用map提取并标准化关键参数(如product_id、region),再用hash $cache_key consistent实现URL参数级一致性哈希,确保相同逻辑请求路由至同一后端。

直接用 url_hash 无法按 URL 参数实现会话一致性缓存,因为它的默认行为是哈希整个 $request_uri(含路径+原始查询参数),而参数顺序、冗余参数或动态值(如 ts=1712345678)会导致相同逻辑请求被散列到不同后端,破坏缓存一致性。
核心思路:先规范化 URL,再哈希
关键不是“用哪个指令”,而是“用什么变量做哈希输入”。Nginx 的 hash 指令支持任意变量,包括自定义的规范化 URI。需两步完成:
- 用
map指令提取并标准化目标参数(例如只保留product_id和region,忽略utm_*、ts等无关参数) - 用
hash指令对这个标准化后的字符串做一致性哈希(推荐加consistent)
具体配置示例
假设业务要求:商品详情页缓存需按 product_id 和 region 两个参数绑定后端,其他参数一律忽略。
在 http 块中添加:
map $args $cache_key {
~*product_id=(\d+)®ion=([a-z]+) "$1:$2";
~*product_id=(\d+)&.*region=([a-z]+) "$1:$2";
~*region=([a-z]+)&product_id=(\d+) "$2:$1";
~*product_id=(\d+) "$1:default";
~*region=([a-z]+) "0:$1";
default "0:default";
}
在 upstream 块中使用:
upstream product_cache {
hash $cache_key consistent;
server 10.0.3.1:8080;
server 10.0.3.2:8080;
server 10.0.3.3:8080;
}
这样,/item?product_id=123®ion=us&ts=123456789 和 /item?region=us&product_id=123&utm_source=ad 都会生成相同的 $cache_key = "123:us",从而路由到同一台后端,保障缓存命中。
为什么不用 ip_hash 或原生 url_hash
ip_hash 绑定的是客户端 IP,多个用户访问同一商品仍会打散到不同节点,缓存无法复用;url_hash(或旧版 url_hash 模块)直接哈希完整 URI,参数顺序一变就失效,且不支持正则提取与标准化。只有显式控制哈希输入源,才能精准实现“基于 URL 参数”的一致性。
生产注意事项
- 确保
ngx_http_upstream_hash_module已编译启用(Nginx 1.7.2+ 内置,无需额外安装) -
consistent参数必须加上,否则增减后端节点时大量缓存 key 会重映射,引发雪崩 - 避免在
$cache_key中引入高基数字段(如用户 ID、随机 token),否则负载会严重倾斜 - 可通过
log_format打印$cache_key值,验证标准化逻辑是否符合预期











