分布式事务。这是个已经被无数次讨论的问题,网上文章多如牛毛。本文从业务底层视角出发,探讨分布式事务究竟难在何处,以及务实的解决之路走向何方,再加一根牛毛... 不过希望本文是比较不一样的视角,能给到读者不同的启发。
在微服务架构流行的背景下,分布式事务的文章多如牛毛,虽然很多将事务一致性与副本一致性混为一谈,也仍不可否认其中相当一部分文章、开源代码,也还是不错的。
然而当你跃跃欲试,期待将业界所谓成熟方案落地,可能很快就会发现现实的骨感 —— 对于大量互联网业务,尤其是在大并发、大量使用 nosql 数据库的微服务架构下,很难落地。
1. 问题简述
分布式事务,即在分布式环境下,对于同一个事务下的几件事情,要么一起完成,要么就和什么都没发生一样。也就是我们一般最关注的,是 ACID 中 的 A,因为拆分了服务之后,每一步远程 RPC 都可能故障。
例如张三给李四转账,张三的钱扣了,李四的钱加了,这两件事情,显然就应该一起完成,或者就都没做。
注意这里不要发散到 paxos、raft 等一致性协议上去,因为他们的领域本来就不同。
paxos 针对的是多个节点重复做相同的一件事情,主要处理的是多副本之间的一致性:
节点1完成任务1
节点2完成任务1
节点3完成任务1
分布式事务则显然不同,它针对的是有几个不同的任务,要捆绑一起完成或失败,重点在整体的原子性:
节点1完成任务1
节点1完成任务2
节点1完成任务3
2. 分析探讨
2.1. 超时的难题
这里开门见山,让我们不妨抛开具体的分析过程,直击问题要害,那就是 —— 超时的处理。
明确的成功 / 失败都好说,但是超时呢,有可能成功了,也有可能没成功。在大量现实场景下,只有明确地知道 A 和 B 的真实执行情况,才能采取对应的后续措施,这点比较显而易见,此处不做展开。
那我们要怎么知道 A 和 B 的真实执行情况呢?“立字据” 成了必然的选择,也就是应该要能对账反查。
2.2. 对账反查能力
A 和 B 这两件事,是关联到一个事务的,这就要求,要有一个唯一事务 ID(这个 ID 还可以绑定一些其他附属信息),我们可以通过这个 ID 来做对账。如果能对账,那么幂等也会顺利成章就支持了。
唯一的事务 ID 生成很简单,如何通过这个 ID 来对账才是关键所在。
为了安全可靠,我们必须使用落地的信息来 “立字据”,ID 要体现在落地的数据中,这样我们就可以事后查询相关数据得知真正执行的情况,从而可以继续将事务推进下去。
接下来我们看不同情况下,落地信息具体如何记录。
2.3. 通过本地日志落地
采用进程本地打日志的方式落地,可以配合网盘或