Skip to content

按权重分发的负载均衡算法怎么实现

约 714 字大约 2 分钟

分布式系统与大数据字节

2025-07-24

⭐ 题目日期:

字节 - 2025/7/16

📝 题解:

要实现按权重分发的负载均衡算法,核心是根据服务器权重分配请求流量,权重高的服务器获得更多请求。以下是两种常见实现方式及代码示例:


1. 随机权重算法(无状态)

原理:根据权重生成虚拟区间,随机数落入哪个区间则选择对应服务器。
特点:无状态、简单高效,适合短连接场景。

import random

class WeightedRandomLB:
    def __init__(self, servers):
        """
        servers: 服务器列表,格式 [("server1", weight1), ("server2", weight2), ...]
        """
        self.servers = servers
        self.total_weight = sum(weight for _, weight in servers)
        # 构建权重累积区间 [0, w1), [w1, w1+w2), ...
        self.accumulated = []
        accum = 0
        for _, weight in servers:
            accum += weight
            self.accumulated.append(accum)

    def get_server(self):
        rand_val = random.uniform(0, self.total_weight)
        for idx, acc in enumerate(self.accumulated):
            if rand_val <= acc:
                return self.servers[idx][0]

使用示例

servers = [("A", 3), ("B", 1), ("C", 2)]  # 总权重6
lb = WeightedRandomLB(servers)
print(lb.get_server())  # 输出:约50%概率返回A,16.7%概率B,33.3%概率C

2. 平滑加权轮询算法(有状态)

原理:动态调整当前权重,避免低权重服务器长时间饥饿。
特点:请求分布更平滑,适合长连接场景。

class SmoothWeightedRoundRobin:
    def __init__(self, servers):
        self.servers = servers
        self.current_weights = {}  # 当前权重动态值
        self.effective_weights = {}  # 有效权重(初始=固定权重)
        for server, weight in servers:
            self.current_weights[server] = 0
            self.effective_weights[server] = weight
        self.total_weight = sum(weight for _, weight in servers)

    def get_server(self):
        # 1. 当前权重 += 有效权重
        for server, _ in self.servers:
            self.current_weights[server] += self.effective_weights[server]
        
        # 2. 选出当前权重最大的服务器
        best_server = max(self.current_weights, key=self.current_weights.get)
        
        # 3. 被选中的服务器减去总权重
        self.current_weights[best_server] -= self.total_weight
        return best_server

使用示例

servers = [("A", 3), ("B", 1), ("C", 2)]  # 总权重6
lb = SmoothWeightedRoundRobin(servers)

# 连续调用6次,输出序列如:A, A, C, A, C, B
for _ in range(6):
    print(lb.get_server())

关键点说明

  1. 权重分配

    • 随机算法:每次独立选择,概率=权重/总权重。
    • 平滑轮询:每轮请求分布严格按权重比例(如上例中3:1:2)。
  2. 动态权重调整

    • 平滑轮询算法通过当前权重 -= 总权重避免权重累积溢出。
    • 可扩展:若服务器故障,可将其有效权重设为0临时剔除。
  3. 适用场景

    • 随机权重:适用于无状态短请求(如HTTP API)。
    • 平滑轮询:适用于需要均匀分配的场景(如TCP长连接)。
  4. 进阶优化

    • 增加健康检查机制,自动跳过故障节点。
    • 结合响应时间动态调整权重(自适应负载均衡)。

两种算法均能实现权重分发,选择取决于具体场景。平滑轮询算法虽稍复杂,但能避免低权重服务器“饥饿”,是生产环境推荐方案。