ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

华为没有公开 MetaERP 的“消息中间件白皮书”,但结合其公开架构(云原生微服务、GaussDB、事件驱动、SLA/子账—总账模型)以及大型 ERP 的通用做法,可以把 MetaERP 在分布式事

华为没有公开 MetaERP 的“消息中间件白皮书”,但结合其公开架构(云原生微服务、GaussDB、事件驱动、SLA/子账—总账模型)以及大型 ERP 的通用做法,可以把 MetaERP 在分布式事 华为没有公开 MetaERP 的“消息中间件白皮书”但结合其公开架构云原生微服务、GaussDB、事件驱动、SLA/子账—总账模型以及大型 ERP 的通用做法可以把 MetaERP 在分布式事务里“事件不丢、不重、不乱序”的机制讲得很具体。核心结论先给MetaERP 不是靠“消息队列本身保证一切”而是用本地事务落库 事务消息/发件箱 分区有序 消费幂等 对账补偿​把“可靠投递”和“顺序性”分开解决可靠靠持久化与确认顺序靠业务键分区正确靠幂等和重放。1. 可靠投递先保证“事件一定产生且不会丢”1.1 本地消息表 / Outbox Pattern业务服务和事件存储在同一本地事务里BEGIN TX INSERT invoice_header / invoice_lines INSERT ar_open_item INSERT outbox_event( event_id, aggregate_id, -- 发票ID event_type, -- AR_INVOICE_CREATED payload, statusPENDING, seq_no, version ) COMMIT要么业务单据和事件一起成功要么一起失败。不会出现在数据库里发票有了、事件没发或事件发了、发票回滚。这是 MetaERP 替代 Oracle EBS“同库触发器”的关键EBS一个库里 PL/SQL 写完 AP/AR/GLMetaERPAR 服务自己落库事件出域后再驱动会计引擎/GL1.2 事务消息 / 发件箱转发Outbox 里的事件由可靠组件投递到消息总线RocketMQ / Kafka 类组件发送前status PENDINGMQ 返回 ACKstatus SENT消费方确认处理完可再标记 PROCESSED可选如果发送失败定时扫描器重捞 PENDING / SENT-BUT-NOT-CONSUMED按 event_id 重发MQ 本身持久化、副本同步、消费者拉取避免 broker 丢消息1.3 At-Least-Once而不是 Exactly-OnceERP 领域通常接受事件可能重复但绝不能丢。所以 MetaERP 的设计目标是投递语义At-Least-Once业务语义Effectively-Once通过幂等实现2. 顺序性不是“全局有序”而是“按业务对象有序”这是最关键的一点。应收模块不会要求全系统所有事件全局保序那样吞吐会崩。它要的是同一张发票 / 同一个客户 / 同一笔合同 的事件不能乱序。2.1 用 Aggregate Key 做分区键事件带业务主键场景分区键发票生命周期invoice_id客户回款核销customer_account_id合同收入确认contract_id预收款prepayment_id消息队列里同一 partition key → 进同一 partitionpartition 内 FIFO消费者单线程处理该 partition于是AR_INVOICE_CREATED AR_INVOICE_APPROVED AR_INVOICE_POSTED AR_RECEIPT_APPLIED AR_INVOICE_CLOSED不会被处理成RECEIPT_APPLIED → INVOICE_NOT_YET_CREATED2.2 事件带版本号 / 序列号每条事件有aggregate_id event_version 1,2,3... event_time global_log_offsetMQ offset消费者处理前检查if incoming.version ! current_version 1: reject / reorder / park如果出现旧事件迟到 → 丢弃或进异常处理缺版本 → 暂停该聚合、触发补事件 / 重放3. 消费端用幂等把“重复”和“乱序”消掉3.1 事件 ID 去重表会计引擎 / GL 接收侧processed_event ( event_id PK, source_system, journal_batch_id, status )再来相同 event_id直接返回成功不再生成第二笔凭证所以即使 MQ 重发 3 次GL 也只有 1 笔应收凭证。3.2 业务状态机校验应收对象有状态DRAFT → VALIDATED → POSTED → PARTIALLY_RECEIPTED → CLOSED收到事件时POSTED 事件当前必须是 VALIDATEDRECEIPT_APPLIED发票必须已 POSTEDCLOSED未清金额必须为 0非法转换进异常事件表告警人工或自动补偿而不是“硬算”3.3 SLA / 会计引擎的幂等映射同一业务事件主账簿借应收 / 贷收入IFRS 账按履约义务管理账加利润中心维度但都来自同一个event_id不会“中国账记了、IFRS 账重复记”。4. 跨服务一致性Saga 补偿而不是 2PCMetaERP 不会用传统两阶段提交把 AR、会计引擎、GL、现金、税务锁在一起那样月结会死。而是AR 本地事务发票成立 → 发 AR_INVOICE_POSTED 会计引擎生成 SLA 日记账 → 发 ACCOUNTING_CREATED GL汇总过账 → 发 GL_JE_TRANSFERRED 现金回款事件 → 发 RECEIPT_CREATED 核销服务应用收款某一步失败不回滚上游数据库发补偿事件 / 标记异常例如会计引擎挂了发票已在 AR 成立会计事件滞留重放后补凭证月结前“未生成会计事件报表”会拦住关账这就是最终一致性 关账强校验。5. 顺序被破坏时怎么办MetaERP 通常有四道防线① 分区有序正常路径不出错按 invoice_id / customer_id 分区。② 版本号拦截迟到事件不污染状态旧事件进来直接 reject。③ 异常事件队列乱序状态不合法金额对不上原单不存在进入ar_event_exception由规则或人工处理。④ 月结对账兜底关账前跑AR 未清项总额 发票 - 收款 - 贷项SLA 日记账 AR 业务事件数GL 应收统驭 子账汇总多账簿来源事件一致只要“事件丢了 / 重复了 / 顺序错了导致少记”关账报表就会爆红。6. 用应收场景串一遍以“发票 → 收款 → 核销”为例AR 服务提交发票→ 同事务写outbox: AR_INVOICE_POSTED事件转发到 MQ→ topic:ar.eventskey:invoice_123会计引擎消费→ 检查event_id是否已处理→ 生成 SLA 凭证→ 发ACCOUNTING_POSTEDGL 消费→ 按source_event_id去重→ 应收统驭科目 1000回款服务发RECEIPT_CREATED→ key:customer_55核销服务消费→ 先见发票 POSTED再见回款→ 更新未清项若回款事件比发票先到→ 发票不存在 / 状态不对→ 进异常队列→ 等发票事件补处理后重放7. 一句话总结MetaERP 保证事件可靠性和顺序性的真实模型是本地事务落 Outbox 保“不丢”​按聚合键分区保“业务内有序”​版本号 状态机保“乱序可发现”​event_id 幂等保“重复无害”​Saga 补偿 月结对账保“最终正确”它不是“消息队列顺序有多强”而是即使消息重复、乱序、延迟财务结果依然可对、可追、可重放、可关账。
返回列表