Skip to content

第 3 章 · 调度算法大全

生活类比:银行大堂经理把客户引到柜台,可以有很多种「规矩」——
按顺序轮流(轮询)、大柜台多接几位(加权)、哪队短去哪(最少连接)、VIP 固定专属经理(粘性哈希)……
没有最好的算法,只有最适合你场景的算法。


3.1 学习目标

  1. 掌握 8 种常见调度算法的工作原理
  2. 能用生活例子向非技术人员解释每种算法
  3. 知道每种算法的适用场景和坑
  4. 能运行 code/lb_simulator.py 观察分发结果

3.2 算法总览

算法英文一句话生活类比
轮询Round RobinA→B→C→A→B→C三个柜台依次叫号
加权轮询Weighted RR能力强的多分配32 核机器多接活
随机Random随机选一台抽签决定窗口
最少连接Least Connections选当前最闲的哪队短排哪
加权最少连接Weighted LC能力×空闲度综合大柜台且队短优先
IP 哈希IP Hash同 IP 总落同一台按身份证号固定窗口
一致性哈希Consistent Hash同 Key 落同一台,扩缩容影响小按会员号固定客服,换人影响小
最短响应Least Response Time选历史响应最快的谁办业务最快找谁

3.3 轮询(Round Robin)— 默认首选

原理

维护一个有序列表,请求按顺序依次分配:

请求 1 → A
请求 2 → B
请求 3 → C
请求 4 → A
...

Nginx 配置

nginx
upstream backend {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}
# 不写任何关键字,默认就是轮询

适用场景

  • 所有后端 配置相同
  • 每个请求处理时间 差不多(都是查数据库返回 JSON)

不适用

  • 机器配置差异大(老机器 2 核、新机器 32 核)
  • 有的请求 10ms,有的 30 秒(长请求会占住连接)

生活例子

食堂 3 个窗口卖同一种盖饭,每个师傅手艺差不多、出餐时间差不多——轮流分流最公平。


3.4 加权轮询(Weighted Round Robin)

原理

给每台机器一个权重 weight,权重越高分得越多。

A: weight=5
B: weight=2
C: weight=1

每 8 个请求 ≈ A 拿 5 个,B 拿 2 个,C 拿 1 个

Nginx 配置

nginx
upstream backend {
    server 10.0.0.1 weight=5;
    server 10.0.0.2 weight=2;
    server 10.0.0.3 weight=1;
}

适用场景

  • 异构集群:新旧机器混部、不同规格云主机
  • 灰度发布:新版本 weight=1,老版本 weight=9

  • 权重是 静态的,不会根据实时 CPU 自动调整
  • 权重拍脑袋容易不准——应结合压测数据

生活例子

银行 3 号窗是新来的实习生(weight=1),1 号窗是资深柜员(weight=5)——同样轮候,资深柜员多接几单才合理。


3.5 随机(Random)

原理

每次从后端池 随机 选一台。长期看趋近均匀,短期可能不均匀。

适用场景

  • 实现简单、无状态、后端同质
  • 客户端 LB 里偶尔使用

  • 短时间内可能「运气不好」全打到同一台
  • 生产环境较少单独使用,多作为基准对比

生活例子

抽奖决定你去哪个窗口——大体公平,但可能连续三次都抽到同一个。


3.6 最少连接(Least Connections)

原理

维护每台后端的 当前活跃连接数,新请求发给连接数 最少 的那台。

时刻 T:
  A: 12 个活跃连接
  B: 3 个活跃连接   ← 新请求给 B
  C: 7 个活跃连接

Nginx 配置

nginx
upstream backend {
    least_conn;
    server 10.0.0.1;
    server 10.0.0.2;
    server 10.0.0.3;
}

适用场景

  • 请求处理时间 差异大(上传文件 vs 查缓存)
  • 长连接 / WebSocket / gRPC streaming
  • 后端会出现「慢请求占坑」

生活例子

超市收银台,经理看一眼——3 号队 2 人、7 号队 8 人,新顾客去 3 号。谁队短去哪,比死板轮询更合理。

与轮询对比(关键面试点)

场景轮询最少连接
请求都是 50ms都很好略好,差别不大
10% 请求要 30s差:慢请求所在机器堆积好:自动避开忙的机器

3.7 IP 哈希(IP Hash)

原理

对客户端 IP 做哈希,同一 IP 的请求总是落到同一后端

nginx
upstream backend {
    ip_hash;
    server 10.0.0.1;
    server 10.0.0.2;
}

适用场景

  • 老系统把 Session 存在 本机内存,必须粘性会话
  • 无 Redis 时的临时方案

坑(重要!)

说明
NAT 共享 IP公司出口一个 IP,上千员工算「一个客户端」全落一台
移动网络 IP 变4G/5G 切换基站,IP 变了,登录态丢失
后端扩缩容节点数量变化,哈希环重算,大量用户「搬家」
分布不均某些 IP 流量特别大(爬虫、大屏),单机热点

生活例子

身份证号后两位 固定窗口——同一个人每次来都找同一个柜员。
但一家人共用一个地址(NAT)就全挤在一个窗口;搬家(换 IP)后要重新分配柜员。

现代最佳实践

不要用 IP Hash 苟会话。把 Session 放到 Redis,用轮询或最少连接——更稳、更均匀。


3.8 一致性哈希(Consistent Hash)

原理(用生活例子理解)

普通哈希:hash(key) % N,N 台机器变 5 台变 6 台时,几乎所有 key 都要重新映射——灾难。

一致性哈希:把后端和 key 都映射到一个 上(0~2³²-1)。

         环上的节点
    A ●─────────● B
       ╲       ╱
        ╲     ╱
         ● C
         
key "user-42" 顺时针找最近的节点 → 落在 B

加一台机器:只影响环上 相邻一小段 的 key,不是全部重来。

适用场景

  • 分布式缓存(Memcached、Redis 集群路由)
  • 同一 URL / 同一用户 ID 要打同一台以提升缓存命中
  • 后端频繁扩缩容

Nginx 配置(需模块支持)

nginx
upstream backend {
    hash $request_uri consistent;
    server 10.0.0.1;
    server 10.0.0.2;
}
# 或 hash $http_x_user_id consistent;

虚拟节点(Virtual Nodes)

真实环境里每台物理机映射 多个虚拟节点 在环上,避免分布不均。

生活例子:不是只放一个「B 客服」在环上,而是放「B1、B2、B3」三个虚拟点,让环更均匀。

与 IP Hash 对比

IP Hash一致性哈希
Key客户端 IP任意(User-ID、URL)
扩缩容几乎全部重映射只影响局部
可控性高(自选 key)

3.9 最短响应时间(Least Response Time)

原理

结合 活跃连接数历史平均响应时间,选「预计最快完成」的节点。

HAProxy 支持较好;Nginx 需第三方或 Plus。

适用场景

  • 后端性能差异 动态变化(有的机器正在 Full GC)
  • 对延迟敏感的业务

生活例子

经理不只看队长短,还看每个柜员 最近平均办一单要多久——队短但柜员特别慢,也不给你。


3.10 算法选型速查表

你的场景推荐算法
同质 Web API,短请求轮询
新旧机器混部加权轮询
长短请求混合、上传下载最少连接
要会话粘性(legacy)一致性哈希 > IP Hash;最好改无状态
缓存集群路由一致性哈希
灰度 10% 流量到新版本加权轮询(新 weight 小)
微服务 gRPC 长流最少连接

3.11 动手实验

bash
# 模拟 3 台后端,发 12 个请求,看轮询分布
python3 code/lb_simulator.py --algorithm round_robin --requests 12

# 模拟处理时间不均时,最少连接 vs 轮询
python3 code/lb_simulator.py --algorithm least_connections --uneven

# 同一用户 ID 是否总落同一台
python3 code/lb_simulator.py --algorithm consistent_hash --key user-42 --requests 10

打开 03_algorithms/demo.html 可视化对比。


3.12 面试题精选

  1. 轮询和加权轮询区别?
    → 轮询均等;加权按 weight 比例分配,适应异构机器。

  2. 什么时候用 least_conn?
    → 请求耗时差异大、长连接场景,避免慢请求导致某台堆积。

  3. 一致性哈希解决什么问题?
    → 节点增减时避免大规模 key 重映射;适合缓存路由。

  4. ip_hash 有什么问题?
    → NAT 不均、移动 IP 变、扩缩容漂移;应优先无状态 + 共享 Session。


3.13 一句话总结

轮询打天下,异构用加权,快慢不一 least_conn,缓存路由一致性哈希,千万别用 IP Hash 当长期方案。

下一章 → 04 · 健康检查:怎么知道后端「病了」?怎么优雅地让它休息?

🎬 可视化演示

打开 03_algorithms/demo.html,点击不同算法按钮,观察 20 个请求如何落到 4 台后端。

🎬 可视化演示

演示加载缓慢或样式异常?点此在新标签页打开 ↗