nginx 无法直接解析数据库分库分表逻辑,但可通过 map 提取分片键、hash 指令(consistent)实现基于键的稳定路由,将相同键请求固定转发至对应 upstream server,配合后端服务完成实际分片。

Nginx 本身不提供“分库分表键”的语义解析能力,也没有内置的、可编程的哈希分片逻辑来直接对接数据库的分库分表策略(比如按 user_id 取模或一致性哈希)。但它可以通过 upstream 模块的 hash 指令,结合变量提取与预处理,实现基于请求中某个键(如 URL 路径、Header、参数)的稳定哈希路由,从而达成“定向集群代理”的效果——即相同分片键的请求始终打到同一组后端服务(例如某分库对应的 API 网关或数据代理层)。
理解 Nginx hash 的作用边界
Nginx 的 hash 是纯负载均衡层面的调度机制,它不理解业务分库规则(如 “user_id % 16 → db_shard_03”),但可以做到:
- 将某个提取出的字符串(如
$arg_user_id或$uri)做一致性哈希或取模哈希; - 把哈希结果映射到预定义的 upstream server 列表中,保证相同输入总落在同一台(或同一类)后端;
- 配合合理的后端抽象(如每个 upstream server 代表一个逻辑分片集群),实现业务层面的“定向”。
提取并标准化分片键(关键前置步骤)
真实业务中,分片键可能藏在不同位置:查询参数(?uid=12345)、请求头(X-User-ID: 12345)、路径(/user/12345/profile)甚至 JWT payload。Nginx 需先将其统一提取为一个变量:
- 用
map指令从多源提取,优先级可控(例如路径 > Header > 参数); - 对键值做清洗:去除空格、强制小写、截断超长值,避免哈希抖动;
- 若需适配数据库分片逻辑(如 32 个库),可提前用
set $shard_key "${cleaned_id}_32";显式标记规模,便于后续扩展。
示例:map $request_uri $shard_key {
~^/user/(\d+)/ $1;
~^/order/(\d+)/ $1;
default $arg_uid;
}
配置一致性哈希 upstream 实现稳定路由
使用 hash + consistent 是最常用方式,能最小化后端增减时的重映射范围:
-
hash $shard_key consistent;—— 对变量内容做 ketama 一致性哈希; - 每个
server行建议加weight=1和唯一id(如id=shard00),便于日志追踪和灰度; - 后端 server 应是逻辑分片入口,例如:
shard00.example.com对应 DB shard 0~3,shard01.example.com对应 shard 4~7,由它们内部完成真正的数据库路由。
示例:upstream db_shard_cluster {
hash $shard_key consistent;
server shard00.example.com weight=1 id=shard00;
server shard01.example.com weight=1 id=shard01;
server shard02.example.com weight=1 id=shard02;
server shard03.example.com weight=1 id=shard03;
}
补充增强:支持动态扩缩与故障隔离
生产环境需考虑可用性与演进性:
- 用
down标记临时下线节点,backup设置热备,避免单点故障导致哈希漂移; - 若需按分片号直连(如
shard_12.example.com),可用rewrite+proxy_pass动态拼接 host,但需确保 DNS 或 service mesh 支持; - 开启
log_format记录$shard_key和选中的$upstream_addr,用于验证路由正确性及问题回溯。
不复杂但容易忽略。











