Apache Ignite 关于 容错(Fault Tolerance)的核心机制
这段内容是 Apache Ignite 关于 容错(Fault Tolerance) 的核心机制——任务失败重试(Failover)。
这在分布式系统中极其重要:节点随时可能宕机、网络可能中断、任务可能出错。Ignite 的“容错”能力就是确保:即使发生故障,任务也不会丢,系统依然能完成工作。
🌐 一句话理解:什么是 Fault Tolerance(容错)?
“不怕出错,错了就换个地方重试” —— 这就是 Ignite 的容错哲学。
就像快递员送包裹:
- 快递员突然生病了 → 公司立刻派另一个快递员接手。
- 只要公司还在运营,你的包裹就不会丢。
Ignite 的 Failover SPI
就是这个“调度替补队员”的机制。
🔧 核心机制:Failover(故障转移)
当一个任务(Job)在某个节点上执行失败时(比如节点宕机、抛异常),Ignite 会自动尝试:
把这个任务“转移”到另一个健康的节点上重新执行。
这个过程对用户是透明的,你提交的任务最终依然会完成。
📌 关键承诺:
As long as there is at least one node standing, no job is ever lost.
只要集群中还有任意一个节点活着,你的任务就不会丢失!
🎯 三种 Failover 策略(SPI 实现)
Ignite 提供了三种内置的故障转移策略:
策略 | 行为 | 适用场景 |
---|---|---|
AlwaysFailoverSpi | 总是尝试重试(默认) | 通用,推荐大多数情况 |
NeverFailoverSpi | 从不重试,失败就报错 | 调试、或任务不允许重复执行 |
JobStealingFailoverSpi | 配合 Job Stealing 使用 | 启用任务窃取时必须配置 |
我们逐个详解。
✅ 1. AlwaysFailoverSpi(默认策略)
🧠 原理
这是最“积极”的重试策略。它会尽一切可能把失败的任务转移到其他节点执行。
🔁 重试顺序(智能转移)
Ignite 不是随便找个节点重试,而是有优先级的:
-
首选:转移到 从未执行过该任务任何子任务的节点
- 目的:避免“同一个节点反复失败”
- 更安全,减少重复失败风险
-
次选:如果找不到“干净”的节点,就转移到 正在执行该任务其他子任务的节点
- 目的:至少保证任务能继续
-
放弃:如果所有节点都不可用或都执行过 → 放弃重试,任务失败
⚙️ 配置示例
<bean class="org.apache.ignite.configuration.IgniteConfiguration"><property name="failoverSpi"><bean class="org.apache.ignite.spi.failover.always.AlwaysFailoverSpi"><!-- 最多重试5次 --><property name="maximumFailoverAttempts" value="5"/></bean></property>
</bean>
✅
maximumFailoverAttempts=5
表示每个失败的 job 最多尝试转移到 5 个不同的节点。
❌ 2. NeverFailoverSpi(禁止重试)
🧠 原理
- 一旦任务失败,立刻报错,不再重试。
- 适用于:
- 调试阶段,想快速看到错误
- 任务具有“副作用”(如发邮件、扣款),不能重复执行
- 强一致性要求,宁愿失败也不乱来
⚠️ 风险
- 节点宕机 → 任务永久丢失
- 不适合生产环境的一般计算任务
配置示例
<property name="failoverSpi"><bean class="org.apache.ignite.spi.failover.never.NeverFailoverSpi"/>
</property>
🦹♂️ 3. JobStealingFailoverSpi(配合任务窃取使用)
🧠 为什么需要它?
还记得前面讲的 Job Stealing(任务窃取) 吗?
- Job Stealing 是“健康节点主动去偷别人队列里的任务”
- 但这涉及到“任务从一个节点转移到另一个节点”
- 这种“转移”本质上就是一种 Failover(故障转移)
所以,只要你启用了 Job Stealing,就必须配置 JobStealingFailoverSpi
,否则无法完成任务转移。
🔗 与 Collision SPI 的关系
<property name="collisionSpi"><bean class="org.apache.ignite.spi.collision.jobstealing.JobStealingCollisionSpi">...</bean>
</property><property name="failoverSpi"><bean class="org.apache.ignite.spi.failover.jobstealing.JobStealingFailoverSpi"/>
</property>
✅ 两者必须配套使用:
JobStealingCollisionSpi
:决定“什么时候可以偷”JobStealingFailoverSpi
:支持“偷成功后如何执行”
🔄 Failover 与 MapReduce 的关系
还记得 ComputeTask.result()
方法吗?
@Override
public ComputeJobResultPolicy result(ComputeJobResult res, List<ComputeJobResult> rcvd) {if (res.getException() != null)return ComputeJobResultPolicy.FAILOVER; // 手动触发重试return ComputeJobResultPolicy.WAIT;
}
这里返回 FAILOVER
,其实就是在调用 Failover SPI!
也就是说:
触发方式 | 说明 |
---|---|
节点宕机 | 自动触发 Failover(由 SPI 处理) |
任务抛异常 | 可通过 result() 方法手动返回 FAILOVER 触发 |
Job Stealing | 通过 JobStealingFailoverSpi 实现任务转移 |
🛡️ 容错流程图(简化版)
提交任务↓
分发到 Node-A 执行↓
Node-A 宕机 或 任务抛异常↓
Failover SPI 被触发↓
查找可用的替代节点(优先选“没执行过”的)↓
任务转移到 Node-B 重新执行↓
成功 → 返回结果
失败 → 继续尝试,直到达到最大重试次数
✅ 实际建议
场景 | 推荐 Failover 策略 |
---|---|
普通计算任务(如统计、分析) | ✅ AlwaysFailoverSpi (默认,推荐) |
任务有副作用(如写数据库、发消息) | ⚠️ 谨慎使用 Failover,或用 NeverFailoverSpi + 外部重试机制 |
启用了 Job Stealing | ✅ 必须用 JobStealingFailoverSpi |
调试阶段 | 可临时用 NeverFailoverSpi 快速定位错误 |
🧠 总结:Fault Tolerance 的本质
机制 | 类比 |
---|---|
AlwaysFailoverSpi | “别放弃!换个人继续干!” |
NeverFailoverSpi | “要么一次成功,要么彻底失败” |
JobStealingFailoverSpi | “你忙不过来?我帮你抢活干,还得合法交接!” |
✅ 最终结论:
Ignite 的容错不是“被动等待恢复”,而是一套主动调度 + 智能转移 + 可配置策略的完整体系。
它和 负载均衡、任务调度 紧密配合,共同保障了分布式计算的:
- 高可用性(High Availability)
- 高可靠性(Reliability)
- 弹性伸缩能力(Resilience)
💡 小贴士:
AlwaysFailoverSpi
+ RoundRobinLoadBalancingSpi
是生产环境最常见的组合,简单、稳定、高效。