最近在看分布式事务的解决方案,讲真方案是真的多,但是我最偏向的是消息补偿,原因当然是简单,但是对于运维是个问题,需要完善的运维工具,否则运维的兄弟们是真的很闹心,原因稍后会有简单表述
项目架构的发展史
软件架构大体可以分为三个阶段,分别是单体架构、分布式架构和微服务架构
单体架构
什么是单体架构,我的理解就是一个应用从开发到部署都是一个war或者是jar,最开始还是不分层的,什么MVC分层之类的最开始都没有,不过不管什么都是慢慢进化的过程,在这过程中我们可以取之精华弃其糟粕,不断完善嘛。
分布式架构
这有分为几种了
1、 应用部署在单服务器,数据库分库分表
2、 应用部署在多台服务器,数据库未分库分表
3、应用部署在多台服务器,数据库也是分布式数据库
这些都算是分布式架构了,分布式架构的好处就是减少单体架构带来的网络IO和服务器内存等的压力,提升用户感知,但是坏处也有,比如所有的功能都在一个war包下,这会给运维和系统扩展带来困难,这就导致微服务架构的诞生
微服务架构
微服务的架构图有点像分布式架构的,区别就是将应用拆开了,如下图:
将应用拆分成多个服务共同为用户提供整体系统功能,这对用户是透明的,操作上和单体架构是一样的,但是用户的感知会更好,不过微服务第一步就是服务边界问题,边界如果拆分不好会造成服务间的边界不明显,增加开发和运维难度,甚至造成返工能风险
单体架构下的事务
单体架构不用考虑什么分布式事务解决方案,单体下的事务是最好解决的,报错了一个回滚即可。就拿转账业务来说,当然是简化的逻辑。
public interface Test {
//用户A账户减去
public void a();
//用户B账户增加
public void b();
}
在转账中会有两个操作,你的账户钱少了100,在用户B的账户中增加100,这就是完整的转账操作,这就完了?当然还没完,这其中还涉及到网络传输,网络在软件行业中是最不可信的,所以一切涉及到网络的都需要考虑到后果。简单来说, 给A用户减去了1000元钱,但是因为网络IO等原因造成B用户的账户没增加这1000元钱,这导致的后果是相当严重的,解决方法是将a和b放在用一个事务中,当b发生异常的时候a不提交事务,回滚操作即可。
什么是分布式事务
这个我们可以看看百度百科的解释:分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。这个应该不难理解,就是说事务相关的节点不在或不全在同一个节点上,为保证数据库的数据一致性,这就产生了分布式事务。
分布式事务的解决方案:
1、基于可靠消息的最终一致性方案
2、TCC事务补偿型方案
3、最大努力通知型
当然这是最终一致性的方案,实时的一致性在分布式事务中是很难或者说是无法做到的,故而只需要保证数据最终一致性即可。
详解分布式事务之消息补偿方案
什么是分布式事务之消息补偿,我还是先上图吧,有图有真相
消息补偿方案在不同的业务下有不同的设计,不过基本思想一样,比如上图所示:
1、用户下单时的所有操作都放缓存里,这里redis是个不错的选择,放缓存的原因是,下一个单子可能会有不同的商品、比如一只笔、一个本子,用户
2、操作完后一次性就将就将数据落入表中,这是第一跳,事务控制,这一般就是在单体应用的事务控制即可。
3、将订单数据落表后就完了?肯定没完啊,比如发送消息通知用户不是,这步就是异步的了,将发送的消息落入表中成功后并将消息体发送到mq主题,之后就是信息服务消费消息将消息发送给用户了
这就是一次完整的流程,当然消息落表失败了,就不会成功将信息发送到用户手中,这可以在服务正常后自动或手动调用接口重新将消息落表并发送mq消息即可,这就是消息补偿。
在开始我就提到“需要完善的运维工具”,这工具最好是自动化运维的,比如重发信息,一两个没问题,如果很多,运维的兄弟可能累死都完成不了
结尾
好了,描述可能不尽如人意,欢迎指正!!!
软件架构是不断进化的,所以需要不断学习与创新,共勉