← 返回题目列表

事件驱动架构有哪些优缺点?

高频 中等 第 6 / 26 题 更新于 2026/10/01
事件驱动消息队列解耦最终一致性
学习 AI 实战项目

简化版

事件驱动架构让生产者发布“已经发生的事实”,多个消费者独立响应,优点是解耦、削峰和易扩展;代价是最终一致性、重复/乱序、Schema 演进、链路排障和运维复杂度。不是把同步 RPC 换成 MQ 就自动得到事件驱动。

详细版

事件应以业务事实命名并由拥有数据的服务发布,包含稳定 eventId、聚合 ID、版本和发生时间。生产者用 Outbox 保证数据与事件一致,消费者幂等、按明确 key 维护局部顺序,失败进入重试和死信。

查询结果或必须立即返回的强一致校验仍适合同步调用;可延后执行、允许最终一致且有多个订阅者的流程更适合事件。落地时必须建设 Schema 治理、追踪、重放、积压容量和对账,而不是隐藏跨服务依赖。

完整版教学

一、事件与命令的区别

命令表达“请做某事”,通常有目标接收者;事件表达“某事实已发生”,可被零到多个订阅者观察。CreateInvoice 是命令,OrderPaid 是事件。把命令伪装成事件会让所有权和失败责任变模糊。

心法:事件用过去式描述不可随意撤销的事实,消费者决定如何响应。

二、解耦带来的收益

订单服务无需知道积分、通知、风控的地址,只发布付款事件;新消费者可独立接入。Broker 缓冲短时峰值,生产者与消费者可按不同速率扩容。故障消费者恢复后从位点继续,不阻塞主交易响应。

Order -> OrderPaid -> [Points]
                    -> [Notification]
                    -> [Risk]

三、解耦不等于没有依赖

依赖从同步 API 转移到 Topic、Schema、语义和时序。生产者删除字段或改变含义会同时影响多个未知消费者;积压让错误延迟暴露。必须有事件目录、owner、兼容规则和影响分析。

事件目录还应标明事实来源和唯一发布者,防止多个服务分别发布语义相近的 OrderPaid,让消费者无法判断哪个才是权威事实。

维度同步 RPC事件驱动
响应即时结果异步收敛
耦合地址/APISchema/语义
故障直接返回积压/重试
排障调用栈Trace+消息轨迹

四、一致性如何建立

业务写成功但事件未发会造成下游永远不知道;先发事件再提交又可能发布不存在的事实。Outbox 把业务数据和事件记录放在同一本地事务,后台至少一次发送;消费者通过 eventId 与状态机幂等。

最终一致性必须有最大收敛时间、补偿和对账,不能只说“过一会会一致”。

五、顺序、重复与重放

Broker 通常只保证分区内顺序,应以 orderId 等聚合 ID 分区。重试和故障切换会重复,跨分区事件会乱序;消费者保存版本、忽略旧事件或等待缺口。重放旧事件时还要保证当前代码兼容历史 Schema。

例如同一订单 v3 先于 v2 到达,消费者不能让 v2 覆盖 v3,可按版本 CAS 更新。

六、何时不该使用

用户登录鉴权、余额是否足够等必须立即得到权威结果的校验,不应为了“解耦”改成异步猜测。团队缺少 Broker 运维、幂等、监控和对账能力时,引入事件会增加事故面。

评审应比较业务延迟容忍、订阅者数量、峰值削峰需求、失败恢复和调试成本。

对只有一个稳定调用者、要求立即反馈且没有削峰需求的流程,同步接口通常更直观;架构选择应服务于约束,而不是追求事件数量。

七、常见误区与追问

  • 误区:用了 MQ 就是事件驱动。 消息可能只是远程命令或异步 RPC。
  • 误区:异步等于完全解耦。 Schema 与业务语义仍是契约。
  • 误区:最终一致性不需要 SLA。 必须定义最大收敛时间和补偿。
  • 误区:事件消费者可以假设只收到一次。 至少一次链路天然可能重复。
  • 追问:数据与事件如何一致? 本地事务 Outbox 或可靠 CDC。
  • 追问:如何排查一次业务? 通过 eventId、traceId、位点和消费结果串联。
  • 追问:事件能修改吗? 已发布事实不可原地改,应发纠正/补偿事件并演进 Schema。

八、加强记忆

事件驱动沿“事实建模—可靠发布—幂等消费—顺序边界—失败恢复—可观测”落地。它用异步与最终一致换解耦、削峰和扩展;依赖并未消失,只是从调用地址转为事件契约,因此 Schema、重放和对账是核心能力。