@windwolf
2020-05-19T06:20:50.000000Z
字数 2173
阅读 285
Sailing
微服务
微服务的好处坏处就不多说了, 网上一找一片, 微服务化也是走向SaaS的必经之路, 那么就要想办法解决微服务所带来的问题. 对全顺所在领域来说, 微服务带来的问题主要有两个:
总体来说, 在做服务切割的时候, 就应该考虑应用场景的事务性. 应该尽量避免跨服务的事务, 能用单机事务就用单机事务, 但跨服务事务是不可避免的. 跨服务事务主要有以下种套路:
我们对这些事务实现方式做一个比较:
事务类型 | 数据完整性 | 性能 | 业务侵入性 | 其他要求 |
---|---|---|---|---|
本地事务 | 局部一致性 | 高 | 低 | |
2PC/3PC | 强一致性 | 低 | 低 | 数据源需支持XA接口.*** |
LCN | 强一致性 | 中 | 低 | 需要独立的TxManager服务. |
TCC | 强一致性* | 中 | 高* | 无 |
消息队列 | 最终一致性 | 较高 | 中** | 无 |
*需要针对每种业务场景分别编写Try/Confirm/Cancel
**需要订阅消息来更新状态, 对于复杂场景, 还需要通过消息订阅来处理事务补偿.
***很多现代数据库不支持基本的ACID,两阶段提交更无从谈起
从上表可知, 每种事务都有其某方面的优势和劣势, 因此也就有其适合的场景.
事务类型 | 应用场景 |
---|---|
本地事务 | 事务无需跨服务. 能使用本地事务的尽量使用本地事务. |
2PC/3PC | 事务参与方较少, 参与方可用性很高. |
LCN | |
TCC | 能解决事务中预留业务资源问题. |
消息队列 | 整个事务由发起方和跟随方组成, 跟随方完成与否不直接影响发起方事务, 或者由事务发起方可以决定事务提交还是回滚.* |
*需要针对每种业务场景分别编写Try/Confirm/Cancel
如果从如何短平快地将Sailing迁移到微服务环境这个角度来看, 那么结果指向LCN. 因为:
- 强一致性分布式事务可以确保服务切分过程中, 架构无需调整.
- 代码侵入性低, 切换到分布式事务成本低.
- 性能可接收. 有测试报告表明, LCN方式在Spring Cloud下, 相比本地事务有大约21%的性能下降.
但这必定只是权益之计. 真正地解决方案还要继续展开探讨.
所有强一致性的方案都存在或多或少的性能问题, 因此需要放弃强一致性, 而考虑最终一致性. 虽然最终一致性是由PAC理论引出来的, 但它很多情况下是作为DDD的一部分来讨论的, 所以我们先来分析以下Sailing和DDD的关系.
DDD中有Entity->Aggregation->Domain这样三层构建块, Entity是数据的载体或者说表现形式; Aggregation是一组由强关联关系的Entity集合, 每个Aggregation都有一个AggregationRoot, 一个Aggregation内, Entity之间都是通过对象直接引用来关联的, 每个AggregationRoot都必须可以用id来索引, 一个Aggregation(包括AggregationRoot和其所关联的其他Entity)是作为一个基本单元操作的; Domain是一组Aggregation的集合, Aggregation之间都是通过id来引用.
拿客户订单系统做个例子: 客户信息是个Entity, 客户地址信息是个Entity, 订单是一个Entity, 订单明细也是一个Entity. 客户信息和客户地址信息是一个Aggregation, 客户信息是AggregationRoot, 客户信息直接引用客户地址信息的列表, 客户地址直接引用所属客户; 订单和订单明细构成一个Aggregation, 订单是AggregationRoot, 订单直接引用订单明细列表, 订单明细列表引用所属订单. 客户Aggregation和订单Aggregation构成一个客户订单Domain.
再看Sailing, Sailing中有Entity->Bill/BillType->Module这三个概念, 和DDD中的概念几乎一一对应; 各项特征也几乎全都满足, 唯一的区别是, Sailing并不硬性限制只能通过Root作为一个单元来查询Entity, 也允许直接查询子Entity, 但不推荐这么做. 查询部分后续章节展开讨论.
因此, 从构建块这个角度来看, Sailing符合DDD架构.
再从通信方式的角度入手来看看事务处理, DDD对事务没有明确的要求, 主要是根据业务场景来选择. 但我们通过对构建块的结构的分析可以总结出这么几点:
目前在Sailing中, Bill/BillType之间的通信主要通过BillTransformer和BillTracking. 如何迁移到消息订阅方式是个挑战.
例如一个单据提交, 大致过程如下: