由于互联网的快速发展,以往的单体架构顶不住这么多的需求,这么复杂的业务,这么大的流量。
单体架构的优势在于前期快速搭建、快速上线,并且方法和模块之间都是内部调用,没有网络的开销更加的高效。
从某方面来说部署也方便,毕竟就一个包,扔上去。
不过随着企业的发展,业务的复杂度越来越高,内部耦合极其严重,导致牵一发而动全身,开发不易,测试不易。
并且无法根据热点服务进行动态的伸缩,比如商品服务访问量特别大,如果是单体架构的话我们只能把整个应用复制多份集群部署,浪费资源。
因此拆分势在必行,微服务架构就这么来了。
拆分之后服务之间的边界就清晰了,每个服务都能独立地运行,独立地部署,所以能以服务级别弹性伸缩了。
服务之间的本地调用变成了远程调用,链路更长了,一次调用的耗时更长了,但是总体的吞吐量更大了。
不过拆分之后还会引入其他复杂度,比如服务链路的监控、整体的监控、容错措施、弹性伸缩等等运维监控的问题,还有像分布式事务、分布式锁跟业务息息相关的问题等。
往往解决了一个痛点又会引入别的痛点,所以架构的演进都是权衡的结果,就看你们的系统更能忍受哪种痛点了。
而今天我们谈及的就是分布式事务这个痛点。
分布式事务是由多个本地事务组成的,分布式事务跨越了多设备,之间又经历的复杂的网络,可想而知想要实现严格的事务道路阻且长。
单机版事务都不会严格遵守事务的严格实现,更别说分布式事务了,所以在现实情况下我们只能实现残缺版的事务。
在明确了事务和分布式事务之后,我们就先来看看常见的分布式事务方案:2PC、3PC、TCC、本地消息、事务消息。
2PC
===
2PC,Two-phase commit protocol,即两阶段提交协议。它引入了一个事务协调者角色,来管理各个参与者(就是各数据库资源)。
整体分为两个阶段,分别是准备阶段和提交/回滚阶段。
我们先来看看第一个阶段,即准备阶段。
由事务协调者给每个参与者发送准备命令,每个参与者收到命令之后会执行相关事务操作,你可以认为除了事务的提交啥都做了。
然后每个参与者会返回响应告知协调者自己是否准备成功。
协调者收到每个参与者的响应之后就进入第二阶段,根据收集的响应,如果有一个参与者响应准备失败那么就向所有参与者发送回滚命令,反之发送提交命令。
这个协议其实很符合正常的思维,就像我们大学上课点名的时候,其实老师就是协调者的角色,我们都是参与者。
老师一个一个的点名,我们一个一个的喊到,最后老师收到所有同学的到之后就开始了今天的讲课。
而和点名有所不同的是,老师发现某几个学生不在还是能继续上课,而我们的事务可不允许这样。
事务协调者在第一阶段未收到个别参与者的响应,则等待一定时间就会认为事务失败,会发送回滚命令,所以在 2PC 中事务协调者有超时机制。
我们再来分析一下 2PC 的优缺点。
2PC 的优点是能利用数据库自身的功能进行本地事务的提交和回滚,也就是说提交和回滚实际操作不需要我们实现,不侵入业务逻辑由数据库完成,在之后讲解 TCC 之后相信大家对这点会有所体会。
2PC 主要有三大缺点:同步阻塞、单点故障和数据不一致问题。
同步阻塞
====
可以看到在第一阶段执行了准备命令后,我们每个本地资源都处于锁定状态,因为除了事务的提交之外啥都做了。
所以这时候如果本地的其他