后端文档教程【免费下载链接】system-design-101Explain complex systems using visuals and simple terms. Help you prepare for system design interviews.项目地址https://gitcode.com/GitHub_Trending/sy/system-design-101点击查看免费下载事件溯源Event Sourcing是一种与常规 CRUD 系统设计截然不同的范式它不再持久化系统的当前状态而是把每一次状态变更都作为不可变事件追加存储事件存储Event Store成为唯一的事实来源source of truth。本指南以电商下单 支付系统为例对照普通 CRUD 设计与事件溯源设计的架构差异并延伸讲解事件溯源在 CDC、微服务通信中的落地形态、与 CQRS 的配合、以及消息可靠性Kafka等关键设计取舍帮助你建立从理论到工程实现的完整认识。一、为什么事件溯源会改变系统设计的哲学事件溯源Event Sourcing的核心转变在于从持久化状态转向持久化事件。在传统设计中数据库里存放的是业务对象的最新快照而在事件溯源中我们只记录发生了什么当前状态是由事件序列重新计算出来的投影projection。这一转变带来两个直接后果确定性Determinism给定同一组事件与相同的回放规则任何时候、任何机器重放这些事件都会得到完全相同的状态。这为系统引入了可复现的、确定性的行为是事件溯源范式区别于普通系统设计的最根本哲学差异。事实来源转移事件日志Event Log / Event Store成为系统的唯一事实来源状态视图只是从事件推导出的派生数据可以随时重建、丢弃、或构建出多个不同的投影。用一句话概括差异文档 中明确提到——The event sourcing paradigm is used to design a system with determinism. This changes the philosophy of normal system designs.事件溯源范式用于设计具有确定性的系统这改变了常规系统设计的哲学。在 数据管理模式文档 中事件溯源也被列为六大核心数据管理模式之一其定义如下事件溯源是一种把应用状态的变更存储为事件序列的模式——不是存储领域数据的当前状态而是存储随时间发生的全部变更事件日志使应用能够重建历史状态并提供变更的审计轨迹。该模式非常适合复杂业务事务、需要审计能力、以及需要回滚或重放事件的场景。二、普通 CRUD 系统设计 vs 事件溯源系统设计以电商下单为例文档用可下单、可支付的电商系统来演示两种设计的对比。两者的本质差异体现在数据写入与状态维护方式上。2.1 普通 CRUD 设计直接改写状态在传统 CRUD 系统中每个业务动作直接对数据库执行增删改查下单Place Order在订单表Order Table插入一行记录订单状态字段被设置为PENDING支付Pay for the Order读取该订单行将状态字段更新为PAID同时更新支付记录。这类设计的特点是数据库只保存最新状态历史过程被覆盖或丢失除非另建流水表每次操作是读取 → 修改 → 覆盖天然面临并发更新的冲突问题无法回答这个订单在过去某个时刻的状态是什么这类历史问题除非额外维护审计日志。2.2 事件溯源设计只追加事实事件溯源系统中同一业务流程被建模为一串不可变事件Event只允许追加append-only禁止修改或删除下单追加一条OrderPlaced事件记录订单 ID、商品明细、金额、下单时间等支付追加一条OrderPaid事件记录支付金额、支付渠道、支付时间等订单当前状态由OrderPlaced、OrderPaid等事件按顺序重放replay计算得出例如已支付 存在OrderPlaced且存在OrderPaid。这种事件即事实、状态即投影的模型带来如下收益完整审计轨迹Audit Trail所有变更过程都永久保留天然满足合规审计需求状态可重建Rebuild随时可以从零重放事件重建任意时刻的状态可回放、可回滚Replay / Rollback发现缺陷后可以修正投影逻辑并重放事件修正结果也可以回滚到过去某个事件点历史查询能力可以回答这个订单在 T 时刻的状态是什么确定性相同事件序列必然推导出相同状态便于测试与调试。在 数据管理模式文档 中事件溯源被明确描述为存储随时间发生的所有变更事件日志允许应用重建过去状态并提供变更审计轨迹在需要复杂业务事务、审计性、以及回滚/重放事件的场景中尤为有益。三、事件溯源的关键组件与数据流一个事件溯源系统通常由以下几部分构成命令Command来自客户端的业务意图如下单支付它是触发事件生成的输入聚合/业务逻辑Aggregate / Domain Logic校验命令是否合法并决定产生哪些事件事件存储Event Store以追加方式持久化事件是唯一事实来源投影Projection / Read Model订阅事件流把事件折叠成便于查询的状态视图如订单当前状态表、用户订单列表。数据流大致为客户端 → 命令 → 聚合校验并产生事件 → 事件存储追加写入 → 投影订阅事件并更新读模型 → 查询接口读取读模型。正因为事件是唯一事实来源如何将事件溯源融入系统 一文指出事件溯源把编程范式从持久化状态转变为持久化事件事件存储即事实来源The event store is the source of truth。这意味着投影读模型是派生的、可丢弃的——即使读模型完全损坏也可以仅凭事件日志重建。四、事件溯源的三种典型落地形态除了作为单个聚合内部的状态管理方式事件溯源在工程中还有三种被广泛验证的落地形态详见 如何将事件溯源融入系统。4.1 作为历史档案纽约时报New York Times案例《纽约时报》网站把自 1851 年以来发布的每一篇文章、图片和署名byline都存入事件存储。原始数据随后被反规范化denormalized成不同的视图views并喂给多个 ElasticSearch 节点以支撑网站搜索。这一案例展示了事件溯源的两大优势海量历史数据的永久保存与同一事实来源驱动多个异构投影不同视图、搜索索引都由同一事件日志派生。4.2 作为数据同步管道CDC变更数据捕获在 CDC 与实时数据 中有详细说明CDC 识别并捕获数据库中发生的数据变更使你能跨多个系统复制和同步数据。其工作流程如下数据变更源数据库中的表发生 insert、update 或 delete变更捕获CDC 工具通过 source connector 连接数据库并读取事务日志transaction logs监控并捕获变更变更处理把捕获的变更处理、转换成下游系统适用的格式变更传播把处理后的变更发布到消息队列并传播到目标系统数据仓库、分析平台、Redis 等分布式缓存实时集成CDC 工具通过 sink connector 消费日志并实时更新目标系统实现无冲突的数据分析与决策。用户只需关心第 1 步其余步骤对其透明。最常见的实现是Debezium Kafka Connect用 Kafka 作为 broker把数据变更从源系统流式传输到目标系统Debezium 提供了覆盖 MySQL、PostgreSQL、Oracle 等主流数据库的 connector。在事件溯源语境下CDC 本质上就是把数据库的变更日志事件化一条条 binlog/WAL 记录被转换为领域事件进入事件流。这也是 数据管理/消息架构演进文档 中列举的 Kafka 典型应用场景之一日志分析、数据流、变更数据捕获、系统监控。4.3 作为微服务之间的通信总线购物车示例事件溯源也可以用于微服务间的消息传递。以购物车服务为例服务对购物车加商品减商品等操作生成各种事件Kafka broker 充当事件存储包括风控服务fraud service、计费服务billing service、邮件服务email service在内的其他服务从事件存储消费事件。关键设计点在于既然事件是唯一事实来源每个服务都可以独立确定自己的领域模型domain model——各服务不必共享数据库或强行对齐表结构而是从同一事件流中按需构建自己的视图。这与 事件驱动的一致性模式 中描述的事件驱动型最终一致性一脉相承服务发出事件其他服务监听事件并更新各自的数据库实例从而达成服务间松耦合但数据一致性被延迟最终一致。五、事件溯源 CQRS读写分离的经典组合事件溯源很少单独使用工程上几乎总是与 CQRSCommand Query Responsibility Segregation命令查询职责分离搭配。原因在于事件日志是追加写的本身非常适合承载写路径但直接按原始事件序列做业务查询往往低效需要为读路径构建独立的、经过优化的读模型。CQRS 的核心思想见 数据管理模式文档把用于查询数据的模型读模型与用于更新数据的模型写模型分离使两者可以独立优化从而改善性能、可扩展性与安全性尤其适合读写需求差异巨大的复杂系统。在 事件驱动的一致性模式 中CQRS 还被列为实现最终一致性的四种模式之一将读写操作分离到不同的、最终一致的数据库中读写模型可分别针对特定需求进行优化。因此典型的事件溯源架构为写路径 命令 → 聚合 → 事件存储读路径 投影 → 读模型可能是物化视图 Materialized View → 查询接口。读模型属于派生数据可以随时从事件流重建这正是事件存储是唯一事实来源的直接推论。物化视图Materialized View作为数据管理模式的补充指物理存储查询结果的数据对象可显著加速复杂计算或聚合类查询——在事件溯源系统中常被用作读模型的实现手段详见 数据管理模式文档。六、引入事件溯源必须面对的工程代价与可靠性设计事件溯源并非银弹。它把系统从状态覆盖变成追加事件也把复杂度从数据库层转移到消息与流处理层。以下是从仓库相关文档中可以确认的几类关键代价与对策。6.1 事件存储的可靠性Kafka 会丢消息吗当 Kafka 被用作事件存储时消息可靠性直接决定事件溯源的正确性。Kafka 是否会丢消息 一文指出一个常见的误解是Kafka 天然保证不丢消息实际上必须理解其架构与配置细节才能判断是否会丢消息并加以防范。消息在 Kafka 生命周期中的丢失可能发生在三段Producer 端producer.send()并不直接发给 broker而是经过应用线程application thread→ 记录累加器record accumulator→ 发送线程sender thread / I/O 线程三个环节。必须正确配置acks与retries才能确保消息到达 broker。Broker 端正常运行的 broker 集群不应丢消息但要警惕两种极端情况——消息通常为追求 I/O 吞吐而异步刷盘若刷盘前实例宕机则消息丢失副本replicas必须配置合理以持有有效数据副本数据同步的确定性至关重要。Consumer 端Kafka 提供不同的提交commit方式。自动提交auto-commit可能在记录真正处理完之前就确认了处理完成若消费者在处理中途宕机部分记录可能永远不会被处理。最佳实践是组合使用同步与异步提交处理循环中用异步提交换取更高吞吐异常处理中用同步提交确保最后一个 offset 总是被提交。6.2 投递语义at-most once / at-least once / exactly once投递语义 一文给出了三种投递语义及其适用场景At-most once最多一次消息不会被重复投递但可能丢失。适合监控指标等允许少量丢失的场景。At-least once至少一次消息不丢失但可能被重复投递。当数据重复不是大问题、或消费端可去重例如给每条消息带唯一 key写库时拒绝重复数据时通常够用。Exactly once精确一次最难实现的语义对用户友好但系统性能与复杂度代价高。特别适合支付、交易、会计等金融场景——当重复不可接受、且下游服务或第三方不支持幂等时尤其重要。对事件溯源而言事件的追加写入天然要求精确一次或至少一次的强可靠投递否则事件日志会出现空洞或重复事件破坏状态重建的确定性。6.3 幂等与重试应对重复事件由于 at-least once 语义下事件可能重复消费端必须具备幂等能力。幂等性的六大应用场景 明确列举了与事件溯源高度相关的场景分布式系统与消息处理中必须确保从队列重复处理同一条消息不会产生重复副作用——处理器要能多次处理同一消息而无副作用数据库操作中重新应用同一事务不应改变数据库状态。在电商订单场景中这也直接对应重复提交订单只产生一个订单重复支付请求只扣一次款的幂等要求见同文档中订单管理系统与支付处理的相关条目。6.4 重试策略避免重试风暴事件消费失败后的重试策略直接影响系统稳定性。重试策略文档 对比了四种常用策略线性退避Linear Backoff间隔固定递增实现简单但在高并发下可能导致资源争用或重试风暴线性抖动退避Linear Jitter Backoff在线性间隔上加入随机抖动分散重试时间降低实例间同步重试的概率但基准间隔仍线性增长指数退避Exponential Backoff间隔按 1s→2s→4s→8s 指数增长直至上限显著降低系统负载与重试碰撞概率适合高负载环境但可能不必要地延迟本可快速解决的故障指数抖动退避Exponential Jitter Backoff指数退避叠加随机抖动可加性抖动或乘性抖动进一步降低重试碰撞是四者中工程上最稳健的选择。6.5 实时更新读模型轮询、SSE 与 WebSocket事件溯源系统中读模型的更新时机与通知方式也是设计要点。短/长轮询、SSE、WebSocket 文档 说明HTTP 服务器无法主动向浏览器发起连接因此需要浏览器或服务器承担实时性职责——短轮询浏览器反复请求直到拿到最新数据、长轮询服务器直到有新数据才返回、WebSocket 与 SSE连接建立后服务器可直接推送数据其中 SSE 单向、WebSocket 全双工。在电商订单场景中订单状态由事件流驱动后前端既可以用轮询拉取投影也可以通过 SSE/WebSocket 订阅状态变化。七、事件溯源在整个模式生态中的位置事件溯源不是孤立的概念而是分布式系统模式与数据管理模式生态中的一环在 七大分布式系统模式 中Event Sourcing与 CQRS、Ambassador、Circuit Breaker、Leader Election、Publisher/Subscriber、Sharding 并列属于面试与实战中最常被使用的分布式设计模式在 六大数据管理模式 中它与 Cache Aside、Materialized View、CQRS、Index Table、Sharding 并列被定义为以事件序列存储应用状态变更、支持重建过去状态并提供审计轨迹的核心数据管理模式在 事件驱动的一致性模式 中事件驱动、后台同步、Saga、CQRS 四种模式共同服务于最终一致性设计其中事件溯源天然契合事件驱动 CQRS的组合。理解事件溯源的关键在于记住三句话事件是事实状态是投影事件存储是唯一事实来源。无论是作为单系统内部的持久化范式还是作为跨微服务的事件总线这一原则始终不变——这正是它改变常规系统设计哲学的根本所在。深入阅读差异文档事件溯源系统设计的差异——本文主题的原始出处含 CRUD vs 事件溯源对比图如何将事件溯源融入系统——纽约时报、CDC、微服务通信三种落地形态CDC实时数据的钥匙——Debezium Kafka Connect 的 CDC 全流程数据管理六大模式——事件溯源、CQRS、物化视图的模式定义最终一致性模式——事件驱动、Saga、CQRS 一致性方案Kafka 是否会丢消息——事件存储可靠性三端分析投递语义——at-most/at-least/exactly once 的取舍幂等性的六大应用场景——重复事件消费的去重保障重试策略——四种退避策略对比赞分享后端文档教程【免费下载链接】system-design-101Explain complex systems using visuals and simple terms. Help you prepare for system design interviews.项目地址https://gitcode.com/GitHub_Trending/sy/system-design-101点击查看免费下载相关推荐猫抓网页视频存到本地从抓到存的完整指南猫抓网页视频存到本地从抓到存的完整指南 培训平台的回放只能在线看右键被禁页面上翻不到任何下载按钮。视频其实是个普通媒体文件只是播放地址藏在网络请求里音视频Elysia事件溯源Event Sourcing模式实现Elysia事件溯源Event Sourcing模式实现 引言为什么需要事件溯源 你是否在开发复杂系统时遇到过这些问题无法追踪状态变化的完整历史、调试时FastStream消息 Event Sourcing事件溯源模式实现FastStream消息 Event Sourcing事件溯源模式实现 概述为什么需要事件溯源 在现代分布式系统中传统的CRUDCreate Read后端消息队列微服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考