在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。为了对用户提供正确的 CRUD 等语义,我们需要保证这些放置在不同物理机器上的副本是一致的。分布式事务在现在遍地都是分布式部署的系统中几乎是必要的。
我们先聊一下啥是事务?
分布式事务、事务隔离级别、ACID我相信大家这些东西都耳熟能详了,那什么是事务呢?
概念:
一般是指要做的或所做的事情。
指作为单个逻辑工作单元执行的一系列操作,要么全部执行,要么全部不执行。
简单的说,事务就是并发控制的单位,是用户定义的一个操作序列。
特性:
事务是恢复和并发控制的基本单位。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
- 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
那什么是分布式事务呢?
这里举个简单的例子:大家可以想一下,你下单流程可能涉及到10多个环节,你下单付钱都成功了,但是你优惠券扣减失败了,积分新增失败了,前者公司会被薅羊毛,后者用户会不开心,
但是这些都在不同的服务怎么保证大家都成功呢? 分布式事务。
分布式事务是指会涉及到操作多个数据库的事务。其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。分布式事务处理的关键是必须有一种方法可以知道事务在任何地方所做的所有动作,提交或回滚事务的决定必须产生统一的结果(全部提交或全部回滚)
比较著名的分布式事务有:
- 2pc(两段式提交)
- 3pc(三段式提交)
- TCC(Try、Confirm、Cancel)
- 半消息/最终一致性(RocketMQ)
这里我就介绍下最简单的2pc(两段式),以及大家以后可能比较常用的半消息事务也就是最终一致性,别的事务都大同小异,都有很多优点。
当然也都有种种弊端:
例如长时间锁定数据库资源,导致系统的响应不快,并发上不去。
网络抖动出现脑裂情况,导致事物参与者,不能很好地执行协调者的指令,导致数据不一致。
单点故障:例如事物协调者,在某一时刻宕机,虽然可以通过选举机制产生新的Leader,但是这过程中,必然出现问题,而TCC,只有强悍的技术团队,才能支持开发,成本太高。
开始介绍这个两个事物吧。
2pc(两段式提交) :
第一阶段:准备阶段(投票阶段) 和第二阶段:提交阶段(执行阶段)
2pc(两段式提交)可以说是分布式事务的最开始的样子了,像极了媒婆,就是通过消息中间件或者全部事务管理来协调多个系统,在两个系统操作事务的时候都锁定资源但是不提交事务,等两者都准备好了,告诉消息中间件或者全部事务管理者,然后再分别提交事务。不管最后结果如何,第二阶段都会结束当前事务
但是问题所在是,如果A系统事务提交成功了,但是B系统在提交的时候网络波动或者各种原因提交失败了,其实还是会失败的。
最终一致性:
整个流程中,我们能保证是:
- 业务主动方本地事务提交失败,业务被动方不会收到消息的投递。
- 只要业务主动方本地事务执行成功,那么消息服务一定会投递消息给下游的业务被动方,并最终保证业务被动方一定能成功消费该消息(消费成功或失败,即最终一定会有一个最终态)。
- 不过呢技术就是这样,各种极端的情况我们都需要考虑,也很难有完美的方案,所以才会有这么多的方案三段式、TCC、最大努力通知等等分布式事务方案,大家只需要知道为啥要做,做了有啥好处,有啥坏处,在实际开发的时候都注意下就好了,系统都是根据业务场景设计出来的,离开业务的技术没有意义,离开技术的业务没有底气。
【本文是51CTO专栏机构“AiChinaTech”的原创文章,微信公众号( id: tech-AI)”】