文章目录
分布式系统中,服务调用失败是 家常便饭 ------网络抖动、服务重启、机房故障......问题不是"会不会失败",而是"失败了怎么办"。Dubbo 提供了多种集群容错策略,面试官问这题,他想听的是:每种策略的原理是什么?适用什么场景?你项目里用的哪种?
先说结论
| 策略 | 行为 | 适用场景 |
|---|---|---|
| Failover | 失败自动切换其他提供者重试 | 读操作(默认) |
| Failfast | 失败立即报错 | 非幂等写操作 |
| Failsafe | 失败忽略,返回空结果 | 日志等非关键操作 |
| Failback | 失败自动记录,定时重发 | 消息通知等最终一致场景 |
| Forking | 并行调用多个,取最快返回 | 实时性要求高的读操作 |
| Broadcast | 逐个调用所有提供者 | 通知所有节点更新缓存 |
一句话记住:Failover 是"换家店试试",Failfast 是"不行就算了",Failsafe 是"忘了这事",Failback 是"回头再说"
Failover:换家店试试
默认策略。调用失败后,自动切换到其他提供者重试。默认重试 2 次(共调用 3 次)。
java
@DubboReference(retries = 2) // 👈 失败重试 2 次,总共调用 3 次
private UserService userService;
yaml
dubbo:
consumer:
retries: 2 # 全局默认重试次数
就像你去餐厅点菜,第一家说"售完了",你自动换第二家点------总有一家能做。
注意 :重试会带来 延迟 (每次超时等一段时间),也可能导致 重复写入 (如果是写操作)。所以 Failover 只适合读操作,写操作必须用 Failfast。
Failfast:不行就算了
只调用一次,失败立即报错,不重试。
java
@DubboReference(cluster = "failfast") // 👈 失败直接抛异常
private OrderService orderService;
适合 非幂等写操作------创建订单、扣款等。重试可能导致重复下单,比失败更可怕。
就像医院挂号------挂不上就挂不上,你不能自动换家医院挂号,因为可能挂重了。
Failsafe:忘了这事
调用失败时忽略异常,返回空结果。
java
@DubboReference(cluster = "failsafe")
private LogService logService;
适合 非关键操作------写日志、发通知、更新缓存等。失败了不影响主流程。
就像你在饭馆吃饭,服务员忘了送小菜------无所谓,不影响吃主菜。
Failback:回头再说
调用失败时,记录请求到失败队列,定时重发。
java
@DubboReference(cluster = "failback")
private NotificationService notificationService;
适合 最终一致性场景------消息通知、数据同步等。失败了不急着重试,后台慢慢补。
就像快递送不到------先放快递柜,回头再来取。Dubbo 默认每 5 秒重试一次失败记录。
注意:如果失败请求堆积太多,可能导致内存溢出。生产环境需监控失败队列长度。
Forking:同时点几家
同时调用多个提供者,取最快返回的那个。
java
@DubboReference(cluster = "forking", forks = 3) // 👈 并行调用 3 个
private SearchService searchService;
适合 实时性要求高 的读操作------搜索引擎、推荐系统等。不追求所有结果,谁最快用谁。
就像你同时叫了 3 辆出租车,谁先到坐谁------快就是正义。
注意:并行调用会浪费服务器资源(3 次调用只有 1 次有效),forks 数量不宜过大。
Broadcast:通知所有人
逐个调用所有提供者,任意一个报错则报错。
java
@DubboReference(cluster = "broadcast")
private CacheService cacheService;
适合 通知所有节点 的场景------更新缓存、刷新配置等。每个节点都得通知到。
就像公司广播------通知所有部门开会,不能漏掉任何一个。
怎么选择
| 操作类型 | 推荐策略 | 原因 |
|---|---|---|
| 读操作 | Failover | 天然幂等,重试安全 |
| 写操作(非幂等) | Failfast | 避免重复写入 |
| 非关键操作 | Failsafe | 失败不影响主流程 |
| 消息通知 | Failback | 最终一致即可 |
| 实时性要求高 | Forking | 并行取最快 |
| 全节点通知 | Broadcast | 每个都得通知 |
Dubbo 集群容错全景
六种策略
├── Failover ------ 失败重试(默认,适合读)
├── Failfast ------ 快速失败(适合非幂等写)
├── Failsafe ------ 安全失败(适合非关键操作)
├── Failback ------ 失败重发(适合最终一致)
├── Forking ------ 并行调用(适合实时读)
└── Broadcast ------ 广播调用(适合全节点通知)
选择原则
├── 读操作 → Failover
├── 写操作 → Failfast
├── 非关键 → Failsafe
├── 通知类 → Failback / Broadcast
└── 实时性 → Forking
核心风险
├── Failover 重试导致写重复
├── Failback 失败队列堆积
└── Forking 并行浪费资源
口诀:Failover换家试,Failfast直接报;
Failsafe无所谓,Failback回头搞;
Forking并行跑,Broadcast全员到;
读写区分最关键,幂等重试才安全
回答技巧与点评
标准回答:Dubbo 提供 6 种集群容错策略:Failover(失败自动重试,默认,适合读操作)、Failfast(快速失败,适合非幂等写操作)、Failsafe(忽略异常,适合非关键操作)、Failback(失败定时重发,适合最终一致场景)、Forking(并行调用取最快,适合实时读)、Broadcast(广播调用所有节点,适合通知类操作)。选择的关键在于区分读写操作和幂等性。
加分回答
- 幂等性是重试的前提:Failover 重试意味着同一请求可能被多次执行,只有读操作和幂等写操作才能安全重试。非幂等写操作(如下单、扣款)必须用 Failfast
- retries 的计算:retries=2 表示失败后重试 2 次,总共调用 3 次(1 次正常 + 2 次重试)。超时时间要合理设置,避免重试导致响应时间成倍增加
- 自定义容错策略:Dubbo 通过 SPI 机制支持自定义 Cluster 实现,你可以根据业务需求实现自己的容错逻辑,比如"失败后降级到缓存"的混合策略
面试官点评
这道题考的是你对 分布式容错设计 的理解。能说出 3-4 种策略算及格,高分的关键在于:讲清楚每种策略的适用场景和风险,特别是 Failover 重试可能导致写重复的问题。如果你能提到幂等性是重试的前提,说明你有实战经验。
内容有帮助?点赞、收藏、关注三连!评论区等你 💪