事件溯源模式下多微服务间Product模型同步方案咨询
事件溯源模式下跨服务Product模型同步方案分析
针对你提出的场景——服务A(CMS)管控仅含id、title、price的Product模型,服务B(Shipping)、C(Emails)需展示该模型数据,且产品目录少变更但有变更可能、管理员需频繁访问B/C业务数据、各服务独立数据库——我整理了三种同步方案的细节、问题,并给出选型建议:
方案1:事件携带完整Product信息
这种方案会在事件中封装Product的全部所需展示信息,比如order_placed事件的结构如下:
{ "order_id": "[guid]", "product": { "id": "[guid]", "title": "Foo", "price": 1000 } }
服务B和C会把商品信息存在订单表的product JSON字段里,展示时直接从本地存储的事件数据中读取,不需要额外调用其他服务。
存在的问题
- 随着B、C业务发展,所需展示的商品信息增多,事件的数据量会越来越大;
- 如果B和C需要的商品信息不一样,事件必须同时包含两者的需求字段(除非拆分出不同的事件类型);
- 要是后续给Product新增字段(比如
color属性),历史订单的商品数据会缺失这个字段,需要回溯更新事件并重放,成本较高。
方案2:事件仅携带Product的GUID
这种方案只在事件里保留Product的唯一标识,order_placed事件结构示例:
{ "order_id": "[guid]", "product_id": "[guid]" }
服务B、C仅在订单表中存储product_id字段,当需要展示商品信息时,实时调用服务A的A/product/[guid]接口获取完整数据。
存在的问题
- B、C会完全依赖服务A,一旦A宕机或者网络出现问题,B、C的商品信息展示功能直接失效;
- 若服务A修改了Product的schema(比如字段增减、类型变更),B、C必须同步修改代码来适配新的接口返回,耦合性很高。
方案3:事件携带Product GUID,B、C独立维护商品表
事件结构和方案2一致,服务B、C各自在本地数据库中维护独立的products表,订单表保留product_id字段,实现A到B/C的商品数据复制。初始化时从A导入商品数据,后续商品信息变更时,通过调用A的接口或直接访问A的数据库同步所需内容。
存在的问题
- B、C初始化阶段必须依赖服务A,若A此时不可用,B、C无法完成商品数据的初始化工作;
- 当A的Product schema变更时,B、C同步数据的逻辑必须跟着修改,而且很容易出现B/C的商品数据和A不一致的情况,数据一致性维护成本高。
选型建议:优先采用方案1
综合业务场景来看,我更推荐方案1。针对新增字段的问题,可以分两种情况处理:
- 如果商品目录本身没有变更(只是新增了字段,历史商品实际有对应值但之前未记录),可以按照既定规则批量更新历史事件,填充缺失的数据;
- 如果商品目录确实发生了变更(比如新增
color字段时,历史商品原本没有这个属性),可以给历史商品设置默认值(比如默认黑色),要么通过更新事件补全数据,要么在代码层面做兼容处理(展示时若无该字段则显示默认值)。
内容的提问来源于stack exchange,提问作者eithed
相关产品推荐
相关产品推荐

