一、三种算法概述
1. IP Hash(IP哈希)
upstream backend {
ip_hash; # 最简单的会话保持
server backend1;
server backend2;
}
特点
-
会话保持:确保同一用户的请求总到同一服务器
-
简单:配置简单,无需额外模块
-
问题:
-
服务器增减时,大部分会话会失效(哈希重分布)
-
如果客户端使用代理或NAT,多个用户可能被分配到同一服务器
-
负载可能不均衡(某些IP段请求特别多)
-
2. 通用Hash(普通模式)
upstream backend {
hash $cookie_session; # 基于自定义变量
server backend1;
server backend2;
}
特点
-
高度灵活:可以基于任意变量哈希
-
支持一致性哈希 :Nginx 1.7.2+支持
consistent参数 -
配置简单:原生支持,无需额外模块
-
适用场景广:可以根据业务需求选择哈希键
3. 通用Hash一致性模式
upstream backend {
hash $key consistent; # 一致性哈希
server backend1;
server backend2;
}
二、核心原理深度解析
IP Hash 原理
// 简化算法
hash = crc32(client_ip) % server_count;
// 实际实现更复杂,考虑了客户端端口
特点:
-
基于客户端IP地址($remote_addr)
-
简单的取模运算
-
无法处理代理/NAT场景
通用Hash(普通模式)原理
hash_value = hash_function(user_defined_key);
server_index = hash_value % total_weighted_slots;
虚拟节点实现权重:
权重配置:server A weight=3, server B weight=2
虚拟槽位:[A, A, A, B, B]
请求哈希后取模5,映射到对应服务器
通用Hash一致性模式原理
哈希环
┌─────────────┐
│ 虚拟节点A1 │
│ 虚拟节点B2 │
请求哈希值 → │ 虚拟节点A2 │
│ 虚拟节点B1 │
│ 虚拟节点A3 │
└─────────────┘
Ketama算法实现:
def ketama_hash(key):
"""标准的Ketama一致性哈希"""
# 1. 为每个服务器生成多个虚拟节点(默认160×权重)
# 2. 将所有虚拟节点放入哈希环
# 3. 对请求key进行哈希
# 4. 在环上顺时针找到第一个虚拟节点
# 5. 映射到实际服务器
三、详细对比表格
| 特性维度 | IP Hash | 通用Hash(普通) | 通用Hash一致性模式 |
|---|---|---|---|
| 哈希基础 | 仅客户端IP | 任意变量($var) | 任意变量($var) |
| 会话保持依据 | IP地址 | 自定义变量值 | 自定义变量值 |
| 权重支持 | ❌ 不支持(权重配置无效) | ✅ 支持(虚拟槽位) | ✅ 支持(虚拟节点倍数) |
| 服务器增减 | 灾难性(大部分会话失效) | 灾难性(全部重分布) | 影响小(仅相邻节点) |
| 负载均衡 | 可能不均衡 | 较均衡 | 最均衡 |
| 算法复杂度 | O(1) | O(1) | O(log N) |
| 内存占用 | 最小 | 中等 | 较大 |
| Nginx版本 | 所有版本 | 1.7.2+ | 1.7.2+ |
| 配置语法 | ip_hash; |
hash $key; |
hash $key consistent; |
四、实际场景表现对比
场景1:服务器扩容(3台→4台)
nginx
# 初始配置
upstream backend {
# 分别测试三种算法
server 192.168.1.10:8080;
server 192.168.1.11:8080;
server 192.168.1.12:8080;
}
结果对比:
IP Hash: 约 75% 会话失效
通用Hash普通: 约 75% 会话失效
通用Hash一致性: 约 25% 会话失效(仅受影响的环区间)
场景2:不同权重配置
upstream backend {
# 测试三种算法的权重支持
server 192.168.1.10 weight=3;
server 192.168.1.11 weight=2;
server 192.168.1.12 weight=1;
}
权重效果:
# IP Hash:完全忽略权重
# 所有服务器接收等量请求(如果IP分布均匀)
# 通用Hash普通:通过虚拟槽位实现
虚拟槽位 = [A,A,A,B,B,C]
请求分布 ≈ 3:2:1
# 通用Hash一致性:通过虚拟节点倍数实现
服务器A:480个虚拟节点 (160×3)
服务器B:320个虚拟节点 (160×2)
服务器C:160个虚拟节点 (160×1)