本文主要讨论数据库的ACID/并发事务可能遇到的问题以及分布式环境下事务处理面临的挑战
部分内容来自于<<从Paxos到ZooKeeper--分布式一致性原理与实践>>
分布式架构
分布式环境的各种问题
-
通讯异常
分布式系统需要各个节点之间进行网络通讯,一般的内存访问延迟在纳秒级别(通常10ns左右),网络延迟一般在0.1-1ms左右(相当于内存访问的105-106倍),消息的丢失和延迟较普遍.
-
网络分区
集群可能会形成多个局部小集群(脑裂),局部集群之间互相无法通信,极端情况下这些小集群会独立完成原本需要整个分布式系统才能完成的功能.
-
三态
分布式环境下网络可能会出现各种各样的问题.每一次请求与响应,存在特有的"三态"概念:
- 成功
- 失败
- 超时
- 请求没有被成功地发送到对方,而是在发送过程中出现了丢失
- 请求成功发送到对方并进行了处理,但是处理完后在将反馈发回的过程中信息出现了丢失
- 请求成功发送到对方,但是没有完成处理(可能机器挂掉了)
前两种都是有明确响应的,超时是没有响应,就比较复杂,需要考虑很多种情况.
最难处理是最后一种成功发送但是处理的时候机器挂掉了的情况,这种情况下需要考虑节点恢复,幂等请求等问题,否则系统在分布式环境下可能会遇到很多问题.这一点我在刷6.824的时候体会很深...一定要把每种情况都思考到了.
-
节点故障
服务器宕机\硬件损坏\天灾人祸...分布式环境下每个节点其实都是不可靠的,需要考虑任何一个节点在任何时刻都有可能挂掉的情况.
事务/ACID
事务(Transaction)也分"单机版"和"分布式版本".在单机环境下我们一般研究ACID就可以了,而在分布式数据库中,数据分散在不同的机器上,如何对这些数据进行分布式的事务处理是一件非常不容易的事情...
我们假设这样一个场景:
一个跨行的转账操作涉及调用两个异地的银行服务,一个本地银行提供的存款服务,一个目标银行提供的存款服务,两个服务本身是无状态切相互独立,共同构成了一个完整的分布式事物.如果从本地银行取款成功,但是因为某种原因目标银行的存款服务失败了,那么就必须要回滚到取款前的状态,否则用户的钱钱就丢惹
从上面的例子我们可以看到,一个分布式事务可以由多个分布式的操作序列组成,比如上例的取款服务和存款服务,通常可以把这一系列分布式的操作成为子事物.
分布式事物也可以被定义为一种嵌套型的事物,同时也具有了ACID事物特性.不过实现分布式的ACID比较难.
ACID
原子性(Atomic)
事务中的各项操作,要么全部被执行要么全部不执行
一句话:
All or nothing~
一致性(Consistency)
事务执行的结果一定是使数据库从一个一致性状态转变到另一个一致性状态,因此当数据库只包含成功事务提交的结果时就能说数据库处于一致性状态.
不过我个人觉得本书对一致性的解释太过概况了,它主要是站在事务本身是否成功执行的角度来看待一致性的.看了下维基百科,做一些补充:
Significant ambiguity exists about the nature of this guarantee. It is defined variously as:
- The guarantee that any transactions started in the future necessarily see the effects of other transactions committed in the past.
- The guarantee that database constraints are not violated, particularly once a transaction commits.
- The guarantee that operations in transactions are performed accurately, correctly, and with validity, with respect to application semantics.
As these various definitions are not mutually exclusive, it is possible to design a system that guarantees "consistency" in every sense of the word, as most relational database management systems in common use today arguably do.
- 保证未来的事务能够看到所有已提交事务的影响
- 数据库的constraints, cascades, triggers什么的不要被违反了
- 事务内部的操作序列都应当是正确的
*注意这里是ACID的一致性不是CAP的一致性..
隔离性
事务的隔离性是指在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰(有点类似多线程).也就是说,不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间.
标准SQL规范定义了4个事务隔离级别
然后有3个可能发生的"非正常"读取现象
网上讲解隔离级别的文章挺多的了,这里就不展开讲了.
主要区分一下不可重复读和幻读:
不可重复读
A non-repeatable read occurs, when during the course of a transaction, a row is retrieved twice and the values within the row differ between reads.
幻读
A phantom read occurs when, in the course of a transaction, two identical queries are executed, and the collection of rows returned by the second query is different from the first.
可以看到两者在一个事务开始后,都读到了某些被其他事务修改了的内容(这些修改都被提交了).不可重复读读到的内容是其他事务UPDATE后的内容,幻读读到的是其他事务INSERT或DELETE后的内容.也就是说前者读到的数据本身内容发生变化但是数据条数没有变,后者读到的数据内容本身没有变化但是因为增删操作导致数据条数发生了变化.
脏读和不可重复读\幻读有相似的地方,不过脏读读取到的都是未提交的数据.当其他事务UPDATE\INSERT\DELETE了部分内容但是还没来得及提交时读取到的这样的数据就是脏读现象.
下表是事务隔离级别vs可能出现的读现象:
Isolation level | Lost updates | Dirty reads | Non-repeatable reads | Phantoms |
---|---|---|---|---|
Read Uncommitted | don't occur | may occur | may occur | may occur |
Read Committed | don't occur | don't occur | may occur | may occur |
Repeatable Read | don't occur | don't occur | don't occur | may occur |
Serializable | don't occur | don't occur | don't occur | don't occur |
对于大多应用场景可以优先考虑Read Committed级别,能够在避免脏读的同时有良好的并发性能.尽管这种级别会导致不可重复读,幻读,第二类丢失更新等.
关于更新丢失可以看这篇文章https://www.jianshu.com/p/71a79d838443
持久性
一个事务一旦提交,他对数据库的变更应该是永久的.
CAP和BASE理论
对于本地事务处理或者是集中式事务处理,我们可以采用ACDI模型来保证数据的严格一致性.而随着分布式事务的出现,传统的单机事务模型已经无法胜任我们的需求.对于一个高访问量,高并发的互联网分布式系统来说,如果我们期望实现一套严格满足ACID特性的分布式事务,很可能出现的情况是系统的可用性和一致性之间出现冲突.CAP和BASE理论对这相关题进行了探讨.
CAP
一个分布式系统不可能同时满足一致性(C:Consistency),可用性(A:Availability)和分区容错性(P:Partition Tolerance)这三个基本需求,最多只能同时满足其中的两项.
一致性
分布式环境下数据在多个副本之间是否能够保持一致的特性.
可用性
系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果.
有限的时间:不同系统的有限时间不同,比如Google百度通常是0.5s,而基于Spark的海量数据查询可能是5到20秒,对于数据量较大的查询\计算甚至需要数分钟.
返回结果:要求系统在完成对用户请求的处理后返回一个正常的响应结果,通常类似于"OutOfMemory"或者"No space left"等提示语,我们依然认为系统不可用
分区容错性
分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障
对于一个分布式系统,分区容错性是最基本的要求.因为既然是分布式的,那么必然可能存在网络分区的问题,就必须对这一问题进行解决,否则还是别用分布式了...因此系统架构设计师往往需要把精力花在如何根据业务特点在C和A之间寻求平衡.
BASE
BASE是Basically Available(基本可用),Soft State(软状态)和Eventually Consistent(最终一致性)三个短语的简写.是基于CAP定理演化而来的,其核心思想是及时无法做到强一致性,但每个应用都可以根据自身业务特点采用适当的方式来使系统达到最终一致性.
网友评论