写点什么

银行业云原生事件驱动架构实践:经验与教训

作者:Chris Tacey-Green
  • 2026-04-08
    北京
  • 本文字数:4893 字

    阅读完需:约 16 分钟

在探讨云平台与强监管行业中的事件驱动架构时,先建立统一的认知基础十分必要。这一话题吸引着背景各异的人群:既有亲历过分布式系统实际挑战的工程师,也有初次接触相关概念的初学者。统一认知之所以重要,是因为事件驱动架构所涉及的概念看似简单,但若从一开始就理解不清,很容易在实践中被误用。

本文基于我在 2025 年慕尼黑 InfoQ 开发者大会上的演讲,总结了在银行业构建与运维云原生事件驱动系统的经验教训。我将从基础概念入手,探讨这类架构风格在监管严格的环境中为何具备吸引力、能实际带来哪些价值,以及会在哪些环节引入风险与复杂性。同时,我还会介绍能让这类系统在生产环境中切实落地(而非仅停留在理论层面)的设计模式与实践方法。

有了这些基础,理解事件驱动架构是什么、适用于哪些场景、带来了哪些权衡取舍以及为何即便存在监管约束,它依然是银行系统的合适选择,都会变得容易得多。

什么是事件?

事件是系统内部发生的某种状态变更。这种变更可由用户操作、异步后台进程或外部系统与平台交互触发。事件既可以携带描述变更情况的数据,也可以作为轻量级通知,仅表明某件事已经发生。

业界对于事件应包含多少数据一直存在争议。有人主张采用极简负载,也有人更倾向于选择包含更丰富内容的消息。我的观点很简单:事件只应包含与该状态变更直接相关的数据,仅此而已。如果某条信息并非该状态变更的固有内容,就不应该出现在事件中。保持事件精简能让系统更易于演进,并降低系统间不必要的耦合。

命令与事件并不相同

事件驱动系统中最重要的区别之一就是命令与事件之间的差异,这也是最容易被误解的概念之一。如果团队模糊了这一界限,最终往往会得到看似事件驱动、却无法实现预期收益的架构。

命令是对执行某项操作的请求,带有明确意图和指向性:由一个系统告知另一个系统执行特定动作。即便采用异步处理,命令依然包含期望某项操作发生的语义。

事件则不同,它是一种事实陈述,表明某事已经发生。发布事件的系统既不要求后续操作,也不期望得到响应。事件可以有多个消费者、单个消费者,甚至完全没有消费者,这些情况都是合理有效的。

这种区别十分重要。将事件当作命令使用会导致耦合更加紧密,并损害系统的长期灵活性。如果希望系统保持适配能力,就需要审慎区分命令与事件。

事件驱动架构的真正含义

有了这些定义,描述事件驱动架构就变得更加容易。它是一种系统通过发布和响应事件来实现通信的架构风格。生产者将事件发送至事件平台,消费者订阅自己关心的事件。生产者无需知晓哪些系统在消费事件,甚至无需关心是否有系统在消费。

事件驱动架构经常与事件溯源相混淆,但二者并非同一概念。事件溯源将应用状态建模为不可变事件序列,而非直接存储当前状态。例如,采用事件溯源的系统不会直接记录购物车中有四件商品,而是存储四条独立的“商品已添加”事件,并通过重放这些事件来推导出当前状态。

事件溯源或许很强大,但也相当复杂,且难以实现到位。更重要的是,它并非事件驱动架构的前提条件。两者经常被放在一起讨论,这是因为事件溯源系统会产生事件,但采用事件驱动通信并不意味着必须使用事件溯源。

云原生实战

云原生并非只是将工作负载运行在云端。云平台几乎可以支持任何运维模式,而云原生系统更强调采用现代工程实践,在设计上具备可扩展性、支持频繁部署,并依靠自动化而非人工操作来完成运维。

这些系统通常采用微服务构建,但模块化单体也同样适用。架构结构并非关键,重要的是采用现代化的 DevOps 实践,例如持续集成、持续部署以及基础设施即代码。在这一背景下,事件驱动架构是顺理成章的选择。它支持异步通信、松耦合与独立部署,与云原生系统的构建和运维方式高度契合。

银行业环境下的约束考量

银行业的特性给架构设计带来了额外的约束。银行是规模庞大、监管严格的机构,承担着保护客户资金的核心责任。监管不仅影响技术决策,还塑造着组织文化、风险容忍度与变革节奏。因此,这类机构对新型架构模式往往持谨慎态度,也就不足为奇了。

与此同时,现代工程实践已不再是可选项。金融系统的规模与复杂度持续提升,客户期望也在不断提高。在天达银行(Investec,一家英南非合资的国际银行及财富管理集团),我们在满足严格监管要求的同时也在积极采用云原生与事件驱动架构。

为什么事件驱动架构很重要

弄清楚了基础概念,事件驱动架构的价值便不难理解。这些优势并非停留在理论层面,而是直接体现在银行业的实际生产场景中。

解耦是最典型的优势之一,这一优势在支付处理方面体现得尤为明显。以交易监控为例,对账户活动进行实时监测、识别可疑行为,是必不可少的风控环节,但这一环节不应处于核心支付执行路径上。支付需要极高的可靠性,而监控可以异步完成。通过发布支付事件让监控系统可以独立进行消费,这两个关注点便能相互隔离。这意味着即便监控暂时不可用,支付流程仍可正常继续,同时监控能力也能独立演进,不会影响支付流程。

图 1:银行系统中的解耦

事件驱动系统还会生成不可变的活动日志。在复杂的支付流程中,事件不仅是辅助性的审计追踪记录,更是业务实际发生情况的真实凭证。活动日志让团队能够清晰地掌握支付全生命周期,提升了故障排查效率,同时也有助于满足监管机构对可追溯性的要求。

扇出是另一大显著优势。单个事件(如支付完成)可触发多个独立流程:更新支付限额、发送客户通知或启动下游对账流程。每个消费者均可独立管理自身的失败与重试,从而让核心支付流程保持简洁。

图 2:银行系统中的扇出

容错能力在受监管环境中尤为重要,尤其是在涉及第三方欺诈引擎等不可靠外部依赖时。事件驱动架构支持分层重试策略、受控退避以及无法自动恢复时的死信处理,既能防止有害事件影响整个系统,也能让故障处理更加安全可靠。

最后,成熟的事件驱动平台具备真正的即插即用能力。新增功能(如奖励计划)可通过订阅现有事件流实现,无需修改核心系统。在事件设计合理且保持稳定的前提下,能够快速扩展能力,避免与原始系统紧密耦合。

痛点与解决方案

事件驱动架构在理论上看似近乎完美,但现实问题很快会显现。这类架构存在切实的痛点,在银行等监管严格的行业中,忽视这些痛点可能引发严重后果。好消息是,业界对这些挑战已有充分认知,并且有成熟可靠的解决方案。

人为层面的挑战

事件驱动架构面临的最大挑战并非技术层面,而是思维模式的转变。工程师需要建立异步通信、最终一致性与独立故障处理的思维,而非默认采用熟悉的同步请求与响应模式。

我们在实践中对此感受尤为明显。在同时采用事件驱动架构与事件溯源的领域,新团队成员通常需要约六个月时间才能达到资深同事的交付效率。初期,团队经常会对非核心的问题进行过度设计,同时又低估了分布式系统中最关键的问题:一致性、重试机制与故障处理。这些挑战带来的组织层面影响十分显著,不容忽视。

工具和赋能

应对人为层面的挑战仅靠良好意愿远远不够,还需要严谨的工具支撑与能力赋能。在前期投入构建完善的开发者平台,搭配设计精良的模板与共享模块,能带来切实有效的提升。已标准化的落地路径可以帮助新团队快速落地事件驱动微服务,避免重复造轮子。

拥有强大的平台还远远不够,培训同样至关重要。为团队配备强大的工具,但他们却不知道这些系统在生产环境中的运行特性,尤其是故障往往发生在凌晨时分,这存在极大的风险。对此,我们让赋能团队与交付团队结对协作,共同设计并构建出小型实用的事件驱动系统,随后投入生产。这种方式远比单纯依赖文档更为有效,也能让团队具备独立构建系统的信心。

早期在标准上达成共识同样重要。预先统一事件契约、权限体系与核心技术方案能够避免技术碎片化,让整个组织更便捷地消费事件。

防止事件丢失或重复

另一个重大挑战是可靠性。在银行业,事件丢失或重复是完全不可接受的。租金支付遗漏、存款重复支付这类问题并非微不足道的边缘情况,这些风险必须在设计阶段就加以解决。

我们依靠发件箱与收件箱模式来降低此类风险。发件箱模式确保状态变更与事件发布在同一事务边界内完成,从而避免事件丢失,再由调度程序将这些事件可靠地发布至事件平台。

图 3:发件箱和收件箱模式

仅靠发件箱模式无法解决重复发送问题,因为事件系统通常只保证至少一次投递。消费者端的收件箱模式可以解决这一问题:每个事件会在业务逻辑执行前被记录,重复事件则直接被忽略。两种模式结合使用,既可避免事件丢失与重复,也无需让每位工程师重复解决相同的可靠性问题。

事件契约是永久性的

事件有助于实现系统解耦,但同时也形成了持久的契约。一旦事件发布,它可能会永久存在,并支持从任意时间点重放。删除或修改事件中的字段可能会导致消费者报错,更糟糕的是,还可能在处理逻辑中引发不易察觉的隐性问题。重写历史事件以掩盖错误会破坏整个架构,应当避免。

看待事件最稳妥的方式是将其视作公共 API。谨慎定义事件,并假定消费者会以你意料之外的方式使用它们。应尽可能避免破坏性变更,若此类变更无法避免,需对事件进行版本控制。在元数据中加入版本标识,可让消费者安全处理多个版本的事件,并在无中断的情况下重放事件流。

将领域事件与集成事件分离能够增加一层保护。领域事件仅针对特定限界上下文,可以更灵活地演进;而集成事件可以跨上下文使用,需要保持稳定且定义清晰。这种分离可避免内部概念泄露到外部契约中,导致后续难以修改。

需要注意事件顺序

事件顺序是一个微妙却至关重要的问题。大多数云原生事件平台会优先考虑可扩展性,而非严格的顺序保证。重试、退避策略与并行处理都可能导致事件乱序到达。这在某些领域中并无大碍,但在另一些场景下则会引发严重问题。

有两种有效方法可以解决这一问题。第一种是显式排序,让事件携带与聚合关联的版本号或序列号。消费者随后通过收件箱逻辑强制保证顺序,仅在已接收到较早事件后才处理当前事件。这种方法有效,但可能会降低系统的伸缩性。

第二种是隐式排序,让领域自己强制执行有效的状态转换。例如,只有当相关受益人存在,支付才能被处理。隐式排序无需显式控制顺序即可保证业务正确性,通常具备更好的伸缩性。这两种方法均有效,关键在于要将排序作为一项主动的设计决策,而不是等到部署到生产环境后才发现其重要性远超预期。

整合在一起

本文所示的事件驱动架构将有界上下文内的领域事件与跨边界的集成事件相结合,并配合收件箱与发件箱模式,构建出高弹性、可伸缩且可审计的系统。每一次有意义的状态变更都会被记录为事件,并在数据持久化的同时被可靠发布;消费者则通过收件箱处理事件,确保幂等性。这种设计能够有效避免事件丢失与重复,这在监管严格的银行业环境中尤为关键。

图 4:完整的架构

将领域事件与集成事件分离尤为重要。领域事件在有界上下文内可自由演进,而集成事件则作为系统间稳定、带版本的契约。我们通过在这些边界对事件进行过滤、聚合与转换,避免了内部领域概念的泄露,让系统能够独立变更而不影响消费者。

解耦同样能带来切实的运维好处。即便下游服务不可用,支付流程仍可继续;可通过订阅现有事件流来实现新的功能,无需改动核心平台。事件还形成了天然的审计追踪记录,为交易生命周期提供端到端的可见性,满足故障排查与监管合规需求。

将这些模式融入共享开发者平台能够实现更统一的落地。服务模板、共享模块以及内置的可靠性机制让团队可以专注于业务逻辑,而非重复解决基础设施问题。同时,培训也能确保工程师理解这些系统在生产环境中的实际运行表现,而不只是知道如何搭建它们。

结论

事件驱动架构既非捷径,也无法带来一劳永逸的效果。它引入了新的复杂形态、新的故障模式,以及对系统设计截然不同的思考方式。但只要谨慎应用,配合清晰的事件契约、经过验证的可靠性模式,以及对工程团队的有力支持,它就能成为构建现代银行平台的坚实基础。

根据我们的实践经验,这种方案让我们在满足严格监管要求的同时依然能够拥抱云原生架构的敏捷性,支撑起高弹性、可扩展且透明的系统。运用得当的话,事件驱动架构不只是一项技术决策,更是一种运维与组织层面的承诺,深刻影响着团队构建、运行和迭代核心系统的方式。

【声明:本文由 InfoQ 翻译,未经许可禁止转载。】

查看英文原文:https://www.infoq.com/articles/event-driven-banking-architecture/