Apache Ignite 关于 **负载均衡(Load Balancing)** 的详细介绍

发布于:2025-08-01 ⋅ 阅读:(22) ⋅ 点赞:(0)

这段内容是 Apache Ignite 关于 负载均衡(Load Balancing) 的详细介绍。这是分布式系统中非常关键的一个机制,决定了任务如何在集群节点之间分配。

我来用通俗易懂的语言 + 类比 + 图解思维,帮你彻底理解 Ignite 的负载均衡机制。


🌐 一句话理解:什么是负载均衡?

负载均衡就是“公平地把工作分给所有人干”,避免有人累死、有人闲死。

就像一个项目经理要把 10 个任务分给 5 个员工:

  • 如果全给一个人做 → 他累垮了,其他人没事干。
  • 如果每人分 2 个 → 工作均衡,效率最高。

Ignite 的负载均衡就是这个“智能分配员”。


🔧 Ignite 负载均衡的三大核心机制

机制 作用
1. Round-Robin(轮询) 默认方式,像发牌一样轮流分配任务
2. Weighted Random(加权随机) 强的机器多干活,弱的少干点
3. Job Stealing(任务窃取) 忙不过来时,别人主动帮你抢活干

下面我们逐个讲解。


🎯 一、Round-Robin 轮询负载均衡(默认)

✅ 原理

像发扑克牌一样,按顺序一个接一个地把任务分给节点

例如有 3 个节点 A、B、C,要执行 6 个任务:

任务1 → A
任务2 → B  
任务3 → C
任务4 → A
任务5 → B
任务6 → C

✅ 这是最简单、最公平的分配方式。

⚙️ 两种模式

模式 特点 适用场景
Global Mode(全局轮询) 所有任务共享一个“发牌顺序” 默认,适合大多数情况
Per-Task Mode(每任务轮询) 每个任务从随机起点开始轮询 保证每个任务都能均匀分布到所有节点
🔍 区别举例:

假设集群有 A、B、C 三个节点。

任务 Global Mode 分配结果
Task1 的 job1 A
Task1 的 job2 B
Task2 的 job1 C
Task2 的 job2 A
任务 Per-Task Mode 分配结果
Task1 开始随机选 B → job1→B, job2→C, job3→A
Task2 开始随机选 A → job1→A, job2→B, job3→C

Per-Task 的好处:即使多个任务并发执行,也能确保每个任务的 jobs 尽量均匀分布。

🛠️ 配置方式(XML)

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="loadBalancingSpi">
        <bean class="org.apache.ignite.spi.loadbalancing.roundrobin.RoundRobinLoadBalancingSpi">
            <property name="perTask" value="true"/> <!-- 启用 per-task 模式 -->
        </bean>
    </property>
    
    <!-- per-task 模式需要开启这些事件 -->
    <property name="includeEventTypes">
        <list>
            <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FINISHED"/>
            <util:constant static-field="org.apache.ignite.events.EventType.EVT_TASK_FAILED"/>
            <util:constant static-field="org.apache.ignite.events.EventType.EVT_JOB_MAPPED"/>
        </list>
    </property>
</bean>

🏋️ 二、Weighted Random 加权随机负载均衡

✅ 原理

不是完全随机,而是根据“权重”来决定谁更可能被选中。

💡 权重越高 → 越容易被分配任务。

举个例子:
节点 配置 权重 分配概率
Node-A 16核 CPU,64GB内存 20 50%
Node-B 8核 CPU,32GB内存 10 25%
Node-C 8核 CPU,32GB内存 10 25%

总权重 = 20+10+10 = 40
Node-A 概率 = 20/40 = 50%

🛠️ 配置方式

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="loadBalancingSpi">
        <bean class="org.apache.ignite.spi.loadbalancing.weightedrandom.WeightedRandomLoadBalancingSpi">
            <property name="useWeights" value="true"/>
            <property name="nodeWeight" value="10"/> <!-- 当前节点的权重 -->
        </bean>
    </property>
</bean>

✅ 你可以为不同硬件配置的服务器设置不同的 nodeWeight,实现“能者多劳”。


🦹‍♂️ 三、Job Stealing 任务窃取(高级功能)

这才是真正的“智能负载均衡”!

❓ 问题背景

传统负载均衡是“提交时决定谁干”(early balancing),但可能出现:

  • 某个节点突然变慢(GC、IO阻塞)
  • 某些任务特别耗时
  • 导致任务堆积,整体变慢

✅ 解决方案:Job Stealing

允许空闲节点“偷走”别人队列里还没开始的任务,自己去执行。

📌 这是一种“事后调整”机制,也叫 Late Load Balancing(延迟负载均衡)

🔄 工作流程:
  1. 所有任务最初按 Round-Robin 分配。
  2. 系统监控每个节点的负载。
  3. 如果发现:
    • A 节点:等待中的任务太多(wait queue 很长)
    • B 节点:很空闲
  4. → B 节点主动向 A 请求:“你那有几个任务还没开始吧?给我两个我帮你做!”
  5. A 把任务“转让”给 B,B 开始执行。

✅ 就像办公室里:小李忙得焦头烂额,小王做完了自己的事,主动说:“你那边还有活吗?我帮你干点。”

🛠️ 配置方式

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <!-- 必须配置对应的 Failover SPI -->
    <property name="failoverSpi">
        <bean class="org.apache.ignite.spi.failover.jobstealing.JobStealingFailoverSpi"/>
    </property>

    <!-- 启用 Job Stealing -->
    <property name="collisionSpi">
        <bean class="org.apache.ignite.spi.collision.jobstealing.JobStealingCollisionSpi">
            <property name="activeJobsThreshold" value="50"/>        <!-- 活跃任务阈值 -->
            <property name="waitJobsThreshold" value="0"/>           <!-- 等待任务超过0个就可被偷 -->
            <property name="messageExpireTime" value="1000"/>        <!-- 消息过期时间 -->
            <property name="maximumStealingAttempts" value="10"/>    <!-- 最大尝试次数 -->
            <property name="stealingEnabled" value="true"/>          <!-- 启用窃取 -->
            <property name="stealingAttributes">
                <map>
                    <entry key="node.segment" value="foobar"/>       <!-- 只在相同segment内窃取 -->
                </map>
            </property>
        </bean>
    </property>
</bean>

⚠️ 注意事项

  • 不是所有任务都能被“偷”:只有还没开始执行的任务(在等待队列中)才能被转移。
  • 需要 Failover SPI 配合:因为任务转移涉及故障恢复逻辑。
  • 增加网络开销:节点之间要频繁通信判断负载。

📊 三种机制对比

特性 Round-Robin Weighted Random Job Stealing
分配时机 提交时决定(Early) 提交时决定(Early) 执行前动态调整(Late)
公平性 中(按权重) 非常高(动态适应)
复杂度
是否需要额外 SPI 是(Collision + Failover)
适合场景 均匀负载 异构集群 动态负载变化大

🚫 什么时候不启用负载均衡?

文档提到:

Load balancing does not apply to colocated computations.

意思是:如果你的任务和数据在同一个节点上(Colocation),就不需要负载均衡。

比如:

  • 你要查 key=123 的数据
  • 数据在 Node-A 上
  • 那么任务必须发送到 Node-A 执行(本地计算)
  • 不能为了“负载均衡”而发到 Node-B,那样反而要远程取数据,更慢!

📌 所以:数据局部性(Data Locality)优先于负载均衡


✅ 实际建议

场景 推荐配置
普通集群,硬件相同 默认 Round-Robin(Global Mode)
硬件差异大(有的强有的弱) Weighted Random + 设置 nodeWeight
任务执行时间差异大,常有“长尾任务” 启用 Job Stealing
强调任务顺序或一致性 可关闭负载均衡,手动指定节点

🧠 总结:负载均衡的本质

机制 类比
Round-Robin 发牌员按顺序发牌
Weighted Random 给能力强的人发更多牌
Job Stealing 发完牌后,发现有人手忙脚乱,旁边的人说:“我帮你出几张!”

最终结论

Ignite 的负载均衡不是“一种”算法,而是一套多层次的智能调度体系

  1. 第一层:提交任务时,用 Round-Robin 或 Weighted Random 初步分配;
  2. 第二层:运行时监控,用 Job Stealing 动态纠偏;
  3. 第三层:遇到失败,用 Failover 重新分配。

这三者结合,才能真正实现“高效、稳定、自适应”的分布式计算。


网站公告

今日签到

点亮在社区的每一天
去签到