首页/开发/系统分析与架构设计速查/事件通知与事件携带状态转移
架构风格与模式58 条

事件通知与事件携带状态转移

事件驱动有三种常见用法:事件通知(薄事件,只告知发生了什么)、事件携带状态转移(事件内含所需数据)、事件溯源(事件即事实来源);耦合度与信息量递增。

两种事件用法

事件驱动里有两种最常用的写法:事件通知是薄事件,只说明发生了什么,消费者需要时回查详情;事件携带状态转移是厚事件,把消费者需要的关键数据直接放进事件体。另有事件溯源把事件序列本身当作事实来源,属于更重的一类选择。三者的信息量与耦合度依次递增。

怎么选

选择依据是消费者需要多少信息,以及能容忍多大的耦合。薄事件让生产者最轻松,但每个消费者都要回查,回查接口一旦不稳定就退化成同步依赖;厚事件让消费者开箱即用,代价是事件契约随业务字段变化,兼容性需要专门治理。

三种用法对比

用法事件内容代价
事件通知标识与类型消费者需回查,产生同步依赖
携带状态转移标识加关键字段快照事件体较大,字段演进需管理
事件溯源完整领域事件序列模型与工具链复杂度高

选型经验

回查成本高倾向携带状态,减少消费者回查
消费者众多且差异大倾向薄事件加稳定查询接口
需要完整审计历史考虑事件溯源
契约稳定性优先薄事件更容易长期兼容

典型使用场景

  • 跨上下文通知:只需告知发生了什么,用薄事件降低耦合
  • 下游需要完整数据:用状态转移避免同步回查
  • 审计与状态重建:需要完整历史时考虑事件溯源
  • 减轻回查压力:消费者多且查询昂贵时倾向携带状态
  • 契约长期稳定:消费者差异大时倾向薄事件加查询接口
两种做法可以混用:对性能敏感的少数消费者携带状态,其余消费者接收薄事件后走稳定查询接口,避免为了统一而牺牲全部场景。

易错点

  • 薄事件加同步回查,实际退化为分布式 RPC,还额外引入了一层消息中间件
  • 厚事件字段随业务变化,消费者兼容性频繁被打断,升级要全网协调
  • 事件里塞入全量实体,事件体膨胀到超出消息中间件的大小限制
  • 把事件当命令使用,发送方期待某个特定消费者执行动作,事件语义被污染

数据来源与参考

  • Martin Fowler bliki《What do you mean by Event-Driven?》(2017)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌