https://blog.csdn.net/vincent_wen0766/article/details/113839442
场景题目:一个供应链系统中,存在商品、销售订单、采购这三个服务,销售订单服务和采购订单服务都需要依赖于商品服务。
- 根据商品的型号/分类/生成年份/编码等查找订单;
- 根据商品的型号/分类/生成年份/编码等查找采购订单
初期方案
严格按照微服务划分的原则将商品相关的职责放在商品系统中。因此,在查询订单与采购订单时,如果查询字段包含商品字段,需要按照如下顺序查询:
- 先根据商品字段调用商品的服务,然后返回匹配的商品信息;
- 在订单或采购单中,通过 IN 语句匹配商品 ID,再关联查询对应的单据
存在的问题:
- 随着商品数量的增多,匹配的商品也越来越多,于是订单服务中包含IN语句的查询效率越来越慢
- 商品作为一个核心服务,依赖它的服务越来越多,同时随着商品数据量的增长,商品服务已不堪重负,响应速度也变慢,还存在请求超时的情况;
- 由于商品服务超时,相关服务处理请求经常失败
数据冗余方案
数据冗余的方案说白了就是在订单、采购单中保存一些商品字段信息。
调整架构方案后,每次查询时,就可以不再依赖商品服务了,提供两种方案
- 每次更新商品时,先调用订单与采购服务,再更新商品的冗余数据
- 每次更新商品时,先发布一条消息,订单与采购服务各自订阅这条消息后,再各自更新商品的冗余数据
问题:
- 数据一致性问题: 如果订单与采购的冗余数据更新失败了,整个操作都需要回滚。这时商品服务的开发人员肯定不乐意,因为冗余数据不是商品服务的核心需求,不能因为边缘流程阻断了自身的核心流程
- 依赖问题: 从职责来说,商品服务应该只关注商品本身,但是现在商品还需要调用订单与采购服务。而且,依赖商品这个核心服务的服务实在是太多了,也就导致后续商品服务每次更新商品时,都需要调用更新订单冗余数据、更新采购冗余数据、更新门店库存冗余数据、更新运营冗余数据等一大堆服务。那么商品到底是下游服务还是上游服务?还能不能安心当底层核心服务?
消息发布订阅方案
- 商品无须调用其他服务,它只需要关注自身逻辑即可,顶多多生成一条消息送到 MQ
- 如果订单、采购等服务的更新冗余数据失败了,使用消息重试机制就可以了,最终能保证数据的一致性
存在的问题:
- 数据冗余,每个服务都需要冗余一份商品数据
- 每个依赖的服务需要重复实现冗余数据更新同步的逻辑
-
解耦业务逻辑的数据同步方案
设计思路:
将商品及商品相关的一些表(比如分类表、生产批号表、保修类型、包装类型)实时同步到需要依赖使用他们的服务的数据库,并且保持结构不变
- 在订单采购、查询等服务时,直接关联同步过来的商品相关表
- 不允许采购、订单等服务修改商品表
- 商品无须依赖其他服务,如果其他服务的冗余数据同步失败,它也不需要回滚自身的流程;
- 采购、订单等服务无须关注冗余数据的同步
此时问题又来了,如何实时同步相关表的数据呢?直接找一个现成的开源中间件就可以了,不过它需要满足支持实时同步、支持增量同步、不用写业务逻辑、支持 MySQL 之间同步、活跃度高这五点要求
有以下几款消息中间件支持: