REA模型实战:用资源-事件-代理构建订单与库存数据模型
发布时间:2026/10/14 13:07:29 锦皓数字建站

REA模型全称Resource-Event-Agent翻译成中文就是资源-事件-代理。我第一次在领域建模的文档里碰到这个词以为又是什么悬在半空中的理论框架直到在一套订单系统的重构里真正把它落地到数据库层才发现这东西对梳理业务边界、定义核心模型的价值被严重低估了。它最早来自会计信息系统研究用来替代传统复式记账的科目表思维但放到现在微服务、DDD、事件驱动这些架构环境下它反而显得更合适。这篇文章我会从理论讲到建模实操再用一个图书商城案例带你完整走一遍流程适合正在做订单、库存、财务相关系统的开发者以及想给自己系统建模找一套靠谱方法论的架构师。1. 项目概述与整体设计思路1.1 为什么我弃用了纯科目表转投REA任何一个做业务系统的人迟早会遇到一个尴尬问题业务方让你把客户到底欠我们多少钱跑清楚但你去翻数据库时发现账务逻辑全散在各张业务表里对不上账。传统做法是给系统套一张会计科目表然后做凭证、做分录。订单来了记一笔应收账款收款来了再记一笔银行存款。这套思路很成熟但有一个致命伤科目是人拍的不是业务自然长出来的。同一个销售场景甲设计成应收账款增加、库存商品减少乙可能设计成主营业务收入增加、库存商品减少不同系统的口径完全对不上。而且科目表的语义离业务太远你想追溯这个订单对应的客户是谁、经手人是谁、卖了哪本书得绕好几张表才能查清楚。REA的思路正好反过来。它不关心你用什么会计科目它只问一个问题这个业务过程中企业的资源发生了什么变化谁参与了变化因为什么事件而变化把这些要素记录下来了记账规则可以通过模型自动推导而不是靠人来填。这意味着你不需要维护一套独立的科目体系业务数据本身就是账。从我实测的经验来看REA特别适合业务和财务一体的系统设计比如电商订单、供应链、库存管理。它能让数据的可追溯性大幅提升而且模型一旦搭好新的业务模式比如预售、分期、兑换通常不用改动道只需要加事件就行。1.2 资源、事件、代理三要素到底指什么REA的核心概念不复杂拆开看就三个词。资源Resource是那些企业能够控制、能够用来创造价值的对象。典型的有现金、库存商品、设备、土地。判断一个东西是不是资源有个简单标准它能不能被某个事件增加或减少如果不能增减它大概率不是资源而只是一个描述性信息。比如图书是资源因为库存入库增加它、销售出库减少它而图书的分类只是图书的一个属性不是独立资源。事件Event是导致资源增减的业务活动。比如销售出库让库存减少现金收款让现金增加采购入库让库存增加。事件是REA模型里最核心的元素它记录了业务实际发生了什么所以事件一般都有时间、地点、数量、金额这些特征。代理Agent是参与事件的人或组织。它分成内部代理和外部代理两类内部代理是公司员工比如销售员、仓管员、出纳外部代理是客户、供应商这些和企业打交道的角色。REA强调每个业务事件不仅要记录发生了什么还要记录谁参与了这个事件这为后续的权限追踪、责任审计提供了依据。我会经常建议团队做一个比喻把资源当作水位事件当作开闸放水或注水代理当作操作水闸的人。整个企业运营就是多个水闸在不同的人操作下把水流从一个池子引到另一个池子的过程。REA就是把这个过程完整记录下来而不是只记两笔借贷符号。2. 核心规则与实操要点2.1 关系约束只有三类二元关系三要素本身不难理解真正的门槛在关系规则上。REA模型规定资源、事件、代理之间只允许出现三类直接关系第一类资源流关系Resource-Event。事件会改变某个资源。比如销售出库事件让库存减少这就是一个资源流关系。这个关系是REA的命脉因为它决定了资源增减的方向和数量。建模时一定要标清楚方向是流入资源还是流出资源。比如发货单上的库存减少方向是出付款单上的现金增加方向是入。第二类控制关系Event-Agent。事件由某个代理执行或发起。比如接收订单事件由客户服务人员发起客户是外部代理客服是内部代理。REA要求一个事件最好同时关联内部代理和外部代理因为这才能回答这笔业务是谁做的、对谁做的。第三类责任关系Agent-Agent。两个代理之间存在某种责任、归属或约定关系。比如销售员-负责-客户就是一种责任关系表示这个客户归这个销售员维护。代理之间的直接联系是允许的但资源之间、事件之间不能像传统ER建模那样随便连线。资源对资源的关系在REA里是不允许的因为资源之间如果没有事件介入它们不会自己互相转换比如现金不能直接变成库存中间一定要经过采购付款和采购入库这类事件。这三条约束看上去限制很多实际上是在逼你把业务逻辑放对位置。刚开始建模的时候会觉得束手束脚建模多了你会发现正是这些约束帮你挡住了很多无效关系。2.2 识别三要素的实用判断标准在实操中团队最容易陷入的争论是这个东西到底算资源还是算事件这里分享几个我长期使用的判断标准每一条都来自实际踩坑。判断资源问三个问题第一它是不是企业能控制的资产或服务第二它有没有数量或金额上的计量属性第三它会不会被某个业务事件改变三个答案都是肯定的才是资源。比如客户就不是资源因为企业不能控制客户客户也不通过事件增减库存图书就是资源。判断事件问两个问题第一它是不是在某个时间点真实发生的业务活动第二它是否直接导致了一组资源的增减如果只是提交按钮被点击或某条记录被删除那只是技术行为不是业务事件。更重要的是一个事件最好对应一个操作动作比如下单和支付应该是两个事件而不是混在一起。因为它们的资源流向不同下单不一定改变资源支付才改变现金资源。判断代理只看一条是不是有行为能力的主体能不能为事件负责。客户、供应商、员工都算但客户等级供应商分类只能算属性。有的团队会纠结自动化程序算不算代理我的建议是初期不要引入系统代理把自动化逻辑放在事件内部处理否则模型会多一层复杂度后面排查问题更费劲。2.3 承诺、执行、接收把事件拆到正确的粒度事件建模最讲究粒度。业务上一个看似简单的销售实际上可以拆成三段客户承诺要买、仓库执行出库、财务收到款项。REA对事件粒度的处理有一个经典分层我把它理解成三个状态。承诺层客户提交了订单表示了一种意向此时资源并没有实际变化也就是传统意义上的在途订单。执行层仓库发货资源真的减少了这是货物流转的实际动作。接收层财务收款现金资源真的增加这是资金流的实际动作。如果你把这三个阶段揉成一个事件比如只建一张销售单表面上很省事但后面的资源追踪会遇到麻烦你是按下单时间算库存还是按发货时间算库存客户付了钱但还没发货那笔钱该怎么记账分开了之后每个事件都有自己明确的资源方向和时点业务上任何一条链路出问题你都知道卡在哪一步。我第一次推进这套拆分的时候业务同事觉得流程变复杂了。等到了做月末对账仓管说发了货、财务说没收到款、客服说客户已下单三张表一对问题当场定位他们才认可这个拆分值。3. 实操过程图书商城REA模型从0到13.1 业务范围与场景盘点空对空讲理论没有说服力我用一个完整的案例走一遍流程。假设你在某图书电商公司要为一个商城系统设计数据模型业务大致包括客户浏览商品后下单支付成功后仓库发货同时公司要向上游出版社采购图书入库月底要统计库存和应收账款。先把业务流程列出来客户下订单客户承诺购买某些图书财务收款客户支付货款现金增加仓库发货库存减少客户收到书采购申请公司向出版社提出采购意向采购入库出版社的货运到库存增加财务付款公司支付给出版社现金减少3.2 资源、事件、代理识别落地按上面讲的判断标准把场景里的元素逐个归类。资源部分比较好找现金和库存图书是最明显的两个资源。你可能想问应收账款算不算资源严格说应收账款在REA里不是一个独立资源它是客户承诺付款和实际收款两个事件之间产生的差额是一个派生结果不用单独建表通过事件关联查询出来就行。这个理解很关键可以避免你建模时设计出一堆性质模糊的中间表。事件部分要按动作来拆按承诺、执行、接收分层事件名称对应资源变化参与内部代理参与外部代理客户提交订单不改变资源承诺客服/系统客户财务收款现金增加出纳客户仓库发货库存减少仓管员承运方/客户采购申请不改变资源承诺采购员供应商采购入库库存增加仓管员供应商财务付款现金减少出纳供应商事件分解完之后代理清单也随之产生客户、供应商是外部代理客服、仓管员、出纳、采购员是内部代理。如果你后续要接绩效分析比如哪个销售员的客户回款最快随时可以在事件和代理之间补充关联属性。3.3 关系建模与数据库表设计有了要素清单下一步是连线。按REA规则我只允许三类关系出现资源-事件、事件-代理、代理-代理。整理成关系清单如下客户提交订单 和 财务收款 都涉及现金资源的增减收款事件让现金增加仓库发货 让库存图书减少采购入库让库存图书增加每个事件都至少关联一个内部代理和一个外部代理财务收款资金流入与仓库发货货物流出之间通过订单承诺建立配对关系客户提交订单 是 财务收款 的前置承诺采购申请是采购入库的前置承诺落到数据库层面一般会用事件表加资源流明细表的方式来建建事件表存储每个业务事件的主信息建资源流表存储资源增减的明细。比如发货事件主表记录事件编号、事件时间、仓管员ID扩展表记录出库了哪几本图书、每本出多少数量。这样一张订单对应多条出库明细一张付款单对应多条付款明细干净清晰。SQL设计大致是这种思路CREATE TABLE event_log ( event_id INT PRIMARY KEY, event_type VARCHAR(50), -- 订单/收款/发货/采购/入库/付款 occurred_at DATETIME, -- 事件发生时间 internal_agent_id INT, -- 内部代理 external_agent_id INT -- 外部代理 ); CREATE TABLE resource_flow ( flow_id INT PRIMARY KEY, event_id INT REFERENCES event_log(event_id), resource_id INT, -- 资源如现金、库存图书 direction VARCHAR(4), -- IN / OUT quantity DECIMAL(12,4), -- 增减数量 unit_price DECIMAL(12,2) -- 涉及金额 );这里有个设计要点direction一定要用明确的IN/OUT不要用正负号。正负号在跨资源对比时容易混淆比如库存减少可以用负数但现金流入又可能是正数看代码的人很容易被绕晕。用字符串注明方向加索引后续查任何资源变动时一清二楚。3.4 从REA回到日常开发模型建好只是第一步你还要和团队惯用的领域驱动设计对接。这里我想强调一个映射关系REA中的每个事件基本可以对应到系统里的一个领域事件或一个聚合根操作每个代理可以对应到用户体系中的参与者每个资源可以对应到领域模型中的聚合根或值对象。比如在订单模块里订单这个聚合根可以承载客户提交订单事件发货单聚合根承载仓库发货事件收款单承载财务收款事件。它们之间通过事件消息或调用关联起来而不是把所有状态生硬地塞进一张订单表里。这种设计的直接好处是订单表不再需要一堆状态字段比如待付款、待发货、已发货、已完成这些状态在前端展示看着直观但它本质上是从多个事件之间的时间关系推导出来的不该散落在状态字段里而应该通过时间轴查询实时计算。我见过太多团队用状态字段掩盖建模缺失最后业务一复杂状态机的分支比代码还多维护成本极高。4. 常见问题与排查技巧实录4.1 建模阶段最常见的4类错误第一个错误把资源直接连资源。有人会把图书资源和供应商资源画一条线表示某本图书由某个供应商供货。这在REA里是违规的因为供应商和图书之间没有发生事件。正确的建模方式应该是供应商通过采购申请和采购入库事件才与图书资源发生关系。如果你发现两张资源表之间需要直接关联通常说明你漏掉了一个业务事件。第二个错误把代理和资源混为一谈。比如把客户信用额度设计成资源。这会导致资源清单越来越乱因为额度不是一个真实存在的可增减资产它是基于多个事件计算出来的结果。每次改动额度时你都要想办法增减它实际上却是在破坏真实的业务事件记录。第三个错误事件粒度不一致。有的流程把下单和付款放一个事件有的流程把一次发货拆成了两个事件。整流整合时会有大麻烦。建议建模前先画事件时序图统一规定只要资源流的流向发生变化就应拆分事件。这是张比较万能的验收标准。第四个错误只用内部代理不记外部代理。很多系统记录了出库人是谁但不记录客户是谁。结果出了账务差异只能查操作人没法查交易对手方对账和审计都困难。我的标准是关键事件必须同时记录内外代理宁可多存一个ID也别等要追溯的时候四处拼接。4.2 落地过程中踩过的真实坑这个模型看起来清爽真正落到项目里还是会遇到几个容易踩的坑。一个是和传统会计科目的共存问题。老系统已经有一套科目表怎么融合我的实践经验是REA不能替代所有的科目逻辑尤其是税务、财务报表这些外部强制要求的东西还需要科目表支撑。但你可以把REA当作凭证生成引擎订单、收款、发货这些业务事件通过规则引擎自动生成会计凭证业务数据和账务数据保持一致。这样既保留合规报表能力又让业务模型保持清晰。注意这不是一笔勾销老账而是让新账有据可查。另一个是查询性能的隐患。事件表和资源流表是一张极其庞大的流水表按事件去查所有历史明细时数据量大了会很慢。我的经验是不要尝试在核心流水上直接做报表查询建议用定期跑批或异步回放的方式生成查询专用的投影表或者按资源ID、代理ID做分区。某次库存对账我就是没注意这个流水表扫了全表导致接口超时加了按资源ID分区之后查询时间直接降了一个数量级。还有一个坑容易被人忽视事件的幂等性。同一个业务事件如果被重复记录比如支付回调重试会导致资源数量被重复增加。所以事件表一定需要一个业务唯一键比如订单号加事件类型的组合约束或者在写入前做幂等校验防止重复叠加。4.3 问题速查表现象可能原因排查与处理库存对不上资源流方向写反或数量为负按资源ID查资源流表检查IN/OUT方向应收款金额错乱订单、收款事件拆分不清确认订单承诺和收款执行是否分开建模数据追溯难缺少外部代理记录补齐外部代理ID检查事件表的代理关联流水表查询极慢未按资源或代理分区增加资源ID分区使用投影表做报表查询重复事件叠加缺少幂等键为事件表增加业务唯一约束状态字段混乱把状态当事件记录去掉冗余状态字段用事件联动推导当前状态写在最后的一点经验要说做REA建模最大的收获我觉得不在于画了一张多漂亮的概念模型而在于它改变了团队的思考习惯遇到业务需求先想清楚资源怎么流动事件怎么记录而不是上来就建列表、加字段。用这种方式把一个图书商城系统重新落地之后我对数据血缘的理解深了一层——每一笔库存、每一分钱都能顺着事件链摸到源头。如果你也想在项目里尝试REA我建议不要一开始就铺太大先拿一个订单加收款的子域试水跑通之后再逐步扩展。等到你需要和财务对账、需要追溯业务异常时你就会发现这个模型带来的方便远超建模时的那点投入。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。