最近比较忙,好久没更新了。这次我们来聊一聊分布式事务。 在微服务体系下,我们的应用被分割成多个服务,每个服务都配置一个数据库。如果我们的服务划分的不够完美,那么为了完成业务会出现非常多的跨库事务。即使按照 DDD 的原则来切分服务还是免不了有的业务场景需要多个业务同时提交成功或者同时回滚的场景。比如会员使用积分下订单这个场景,那么会员服务的积分扣减需要跟订单下单成功同时完成。如果下单成功,但是扣减积分接口失败,那么就会造成数据的不一致性。这个时候我们就需要使用分布式事务来保证数据的一致性。 由于分布式事务要介绍的东西比较多,这一篇只介绍 2PC、3PC 的基本概念,所以 .net 相关的内容大概也只会出现在标题上一次,笑哭。
2PC 既 Two-phase Commit ,中文翻译为二阶段提交。2PC 要求每个事务的参与方都把一个事务抽象成2个阶段。下面大概分析下 2PC 事务的流程。 首先提出2个概念:
事务开始后,协调器下达事务开始的命令,每个参与方收到命令后开始执行准备阶段(Prepare phase),所谓准备阶段就是执行本地事物,这个时候资源被锁定,但是不进行提交。如果这个阶段没有发生异常,那么参与方会通知协调器“执行成功”。如果某个参与方在这个阶段失败了,那么同样通知协调器“执行失败”,协调器会给所有参与方发布回滚的命令。参与方在收到“回滚”命令后执行回滚操作。
如果所有的参与方在阶段一全部响应成功,那么协调器就会给每个参与方发布执行提交操作的命令。参与方收到提交命令后开始尝试进行事务提交。如果事务提交成功,参与方会通知协调器“提交成功”。待到所有的参与方全部回复“提交成功”,那么本次事务成功执行。
到这里我们可以看到 2PC 模型跟数据库的事务模型是高度契合的,所以 2PC 经常用来把多个数据库事物包装成一个分布式事务的场景。事实上大多数数据库如:oracle,mysql等自己已经实现了基于XA协议的2PC 事务。
由于 2PC 的众多问题,又有人发明了 3PC 事务。 3PC 事务是对 2PC 的一次改进:
以上简单介绍了 2PC、3PC 分布式事务的原理。我们可以看到 2PC 在理想情况下是可以保证数据一致性的。但是在复杂的生产环境下服务器宕机、网络故障的情况时有发生,最终导致数据的不一致,并且 2PC 的性能也差强人意。3PC 虽然改进了 2PC 的一些缺点,但是仍然没有解决掉最致命的数据不一致的问题、以及性能的问题。所以 2PC、3PC 并不是分布式事务的首选方案。那么下期我们将继续这个话题,继续介绍 TCC 分布式事务。