← 返回题目列表

本地事件总线和消息队列都用了观察者思想,它们怎么选?

高频 中等 第 3 / 27 题 更新于 2026/08/02
观察者模式事件总线消息队列架构选型

简化版

本地事件总线适合同进程内解耦,调用轻、延迟低、实现简单,但不适合跨服务可靠投递;消息队列适合跨进程异步通信、削峰、重试和可靠投递,但引入运维、序列化、幂等和最终一致性成本。选择时看边界:同应用内非关键扩展用本地事件;跨服务、需要可靠、需要削峰或消费者独立扩缩容时用 MQ。

详细版

本地事件总线和 MQ 都体现了观察者思想:发布方发布事件,订阅方响应事件。但它们解决的问题不一样。

本地事件总线:

same process:
  publisher -> event bus -> listener A/B/C

消息队列:

service A -> broker -> service B/C/D

本地事件总线更轻,适合应用内模块解耦;MQ 更重,但能跨进程、跨服务,支持可靠投递和流量缓冲。

记忆钩子:本地事件总线解耦代码模块,消息队列解耦服务和流量。

完整版教学

面试提示:本题不要只比较“本地快、MQ 稳”,要围绕事务边界、可靠性、扩展范围和故障隔离说明选型。

一、两者都像观察者,但边界不同

观察者模式的核心是一对多通知。本地 EventBus 把这种通知放在进程内;MQ 把这种通知扩展到进程外、服务间。

观察者模式思想
  -> 本地事件总线: 内存级通知
  -> 消息队列: 分布式通知

所以不要只因为“都是发布事件”就把它们当成同一个东西。

二、本地事件总线的优势

本地事件总线适合:

  • 同一个应用内部模块解耦;
  • 监听器执行很快;
  • 不要求进程崩溃后继续投递;
  • 不需要跨服务消费;
  • 事件量较小。

例如订单模块发布 OrderPaidEvent,同应用内的日志、指标、缓存刷新监听器响应。

优势是简单、延迟低、没有序列化和网络成本。

三、本地事件总线的局限

局限也明显:

问题说明
进程崩溃内存事件可能丢失
跨服务无法直接通知其他进程
削峰无法像 MQ 一样堆积流量
重试通常要自己实现
可观测需要自己补监听器状态

如果订单支付后必须通知仓储系统发货,只靠本地 EventBus 通常不够。

四、消息队列适合跨服务可靠通知

MQ 适合:

  • 跨服务通信;
  • 异步削峰;
  • 消费失败重试;
  • 消费者独立扩容;
  • 事件可靠投递;
  • 业务最终一致性。

典型链路:

订单服务 -> OrderPaid 消息 -> MQ
  -> 仓储服务消费
  -> 积分服务消费
  -> 营销服务消费

发布方不需要知道有几个下游服务,下游也可以独立扩容。

五、MQ 的代价也要说清

MQ 不是“高级版观察者”这么简单,它会带来:

  • 消息重复;
  • 消息延迟;
  • 顺序消费限制;
  • 消费幂等;
  • 死信队列;
  • 消息堆积;
  • 运维和监控;
  • 事件 schema 演进。

所以同进程内一个简单缓存刷新,不要动不动上 MQ。

六、可以组合使用

实际项目经常组合:

应用内:
  DomainService -> local event -> write outbox

应用外:
  outbox relay -> MQ -> downstream services

也可以主流程先写本地事件表,再由异步任务发 MQ。这样兼顾事务一致性和跨服务通知。

七、选择标准要落到业务问题

判断问题倾向本地事件总线倾向 MQ
是否跨服务
是否要求可靠投递
是否需要削峰
消费者是否独立扩容
是否能接受最终一致性不一定通常需要
运维复杂度

面试中最好用这些维度回答,而不是说“MQ 更强”。

八、常见误区与追问

  • 误区:本地 EventBus 可以替代 MQ。 它无法解决跨进程可靠投递、削峰和消费者独立扩容。
  • 误区:MQ 一定比本地事件好。 简单应用内解耦用 MQ 会增加不必要复杂度。
  • 误区:用了 MQ 就不用观察者模式。 MQ 仍然体现发布订阅思想,只是工程边界更大。
  • 误区:本地事件一定同步,MQ 一定异步。 本地也可异步,MQ 也可能被同步等待,但典型语义不同。
  • 追问:订单支付后发短信用哪个? 同应用内非关键短信可本地异步;跨短信服务或要求可靠重试时用 MQ。
  • 追问:本地事件丢失怎么办? 需要可靠时用事件表、Outbox 或 MQ,不要只靠内存事件。
  • 追问:为什么 MQ 要幂等? 至少一次投递、重试、rebalance 都可能让消费者重复收到消息。

九、加强记忆

  1. 本地事件总线用于进程内模块解耦。
  2. MQ 用于跨服务、可靠投递、削峰和独立扩容。
  3. 本地事件简单低延迟,但进程崩溃可能丢。
  4. MQ 能力强,但带来重复、延迟、幂等和运维成本。
  5. 可靠跨服务事件常结合 Outbox 和 MQ。
  6. 选择看边界和可靠性,不看名字像不像。