说透分布式事务
在《分布式事务:从刚性事务到柔性事务》中,讲过分布式事务。晚上打开微信发现咱们【编程一生】用户群里又讨论起来了。觉得有必要再讲一遍。
分布式事务的本质
事务起源
事务本意就是要处理的事情。计算机中引入了这个词用来表示要处理事情的单元。单元是不可再分的,在数据库中就把这种不可再分给出了明确的特性定义,就是ACID原则。为了和分布式系统中的事务做区分,又叫刚性事务。
ACID原则
● 原子性(Atomicity)
事务必须要么全都执行,要么全都不执行。
● 一致性(Consistency):
保证数据的完整性。事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
● 隔离性(Isolation)
一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
● 持久性(Durability):
一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响,该修改即使出现系统故障也将一直保持。
什么事儿都有个程度。人和人之间的认知是不一样的。举个真实的例子:有次我带儿子去参加公司的轰趴。大家在玩三国杀,我不会。我只是象征性的问我儿子会不会。他斩钉截铁的说会。我明知道他的水平还是让他试了试。结果十几个同事和我儿子展开了异常艰难的对决。这个对决让我充分意识到吃饭时我发的200元红包发少了,太对不起大家了。
儿子的会,连我这个不会的人都开出来他分不清敌我。我们同事们高风亮节,让这么一个人在三国沙场上活到了最后。
回到事务的ACID特性。事务隔离性有四个级别。在《MySQL常见6个考题在实际工作中的运用》中有介绍,这里不赘述。重点讲一致性的三个级别。
数据一致性三个级别
强一致性(Strict Consistency)
也称为:原子一致性(Atomic Consistency)线性一致性(Linearizable Consistency)
强一致性有两个要求:
● 任何一次读都能读到某个数据的最近一次写的数据。
● 系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。
顺序一致性(Sequential Consistency)
有两个要求:
● 任何一次读都能读到某个数据的最近一次写的数据。
● 系统的所有进程的顺序一致,而且是合理的。即不需要和全局时钟下的顺序一致,错的话一起错,对的话一起对。
弱一致性
数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。
其实每个级别都还可以细分。这里只讲一种和今天主题相关的:最终一致性。它属于弱一致性。
最终一致性
不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。
简单说,就是在一段时间后,节点间的数据会最终达到一致状态。
在数据库事务定义ACID的时候,没有想那么多。其实数据库事务中的一致性是强一致。但是强一致到了分布式系统中就遇到了困难。
CAP定理
CAP定理是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足下面3个属性:
○ 一致性(Consistency) :客户端知道一系列的操作都会同时发生(生效)
○ 可用性(Availability) :每个操作都必须以可预期的响应结束
○ 分区容错性(Partition tolerance) :即使出现单个组件无法可用,操作依然可以完成
在分布式系统中,一个Web应用至多只能同时支持上面的两个属性。显然,任何横向扩展策略都要依赖于数据分区。因此,设计人员必须在一致性与可用性之间做出选择。
孔子曾经曰过:没有100分的爱人,只有50分的两个人的共同努力。那聪明的工程师就想了:一个WEB应用至多能支持两个属性达到100分,也就是200分。那我能不能让三个属性都支持到60分。3*60分=180分。200分是上限的话,还可以根据应用自身的需求决定把剩余20分应用到哪方面的提交。这三个60分是什么标准呢?这就是BASE理论。
BASE理论
● Basically Available(基本可用)
● Soft state(软状态)
● Eventually consistent(最终一致性)
BASE理论和分布式事务到底有什么关系呢?我搜索了一下,发现没有一篇文章真正把它们的关系说明白。网上的东西给我感觉:它们觉得有关系,又不明白关系到底是啥。
分布式事务与BASE理论的关系
既然是事务要遵循的是ACID特性。分布式系统与单机在隔离性和持久性上没有明显的差异。所以重点关注的是原子性和一致性。原子性是说要么全做,要么全都不做,这样数据就是一致的。所以原子性是因,根本要保证的数据一致性。
所以实际工作中,我很少听到谈论具体问题的时候用分布式事务这个概念,更多的是说数据一致性。我之前写的《数据一致性-对账》这篇文章里提到了好几种分布式事务常用的手段,但是我没有说分布式事务这个词。工作中用这个词,具体解决的问题不明确,不建议用,建议把具体要解决的问题想清楚。既然解决的问题是数据一致性问题,web服务不能不考虑可用性,单纯只保证一致性,所以就要考虑BASE理论了。觉得我没讲清楚的扣圆周率小数点后四位。
你真的需要分布式事务吗?
既然分布式事务根本上解决的是分布式数据一致性问题,在大多数问题上使用seata等框架太重了。咱们平时有很多简单有效的方法一直在用。
比如支付交易中,有典型的补偿型数据一致性保障:发起一笔支付没有收到响应,可以使用补偿查询作为第一层数据一致性保障;查询半小时还是查不回来,就关单操作,该冲正的冲正(取消交易,已付款退回账户中),这是第二层数据一致性保障;清结算之前还要对账(做核对校验,对不上人工处理),这是第三层数据一致性保障。在《程序常用的设计技巧》里我也提过其他的补偿性方案。
总结
看问题还是要从本质问题出发,最好不要引入额外的概念引起歧义。
文章转载自公众号:编程一生