随着现代互联网的发展,业务不断扩张,对于项目的吞吐量,稳定性,可用性方面都有了更多的要求,单一的系统架构已经不能满足当前的业务需求了。更小更灵活的服务集群从成本,可用性,稳定性的角度考虑更符合公司的需要,因此,是非常有必要了解一下这些东西的。
CAP定理
cap是指分布式数据存储中,C:一致性(Consistency),A:可用性(Availability),P:分区容错(Partition tolerance)三者之间只能同时保证两者以上。
一致性,指数据在多个副本之间保持严格一致性。
可用性,指服务是可用的,使用的时候不会出现非错的响应。
分区容错:在出现网络分区故障的时候,依然可以提供保证一致性和可用性的服务。
至于为何不能三者同时满足,简单说明的话是首先一致性在一定程度上可以理解为原子性,在出现网络分区的时候是无法实现原子性的,除非停止服务,因此就丧失了可用性,为CP;同样,如果在一致性的基础上保证可用性的话,就不能存在分区容错,只能是一个整体性的应用,此为CA,如果需要使分区都可以正常工作,那么就需要接受分区之前不能进行网络通信,这样一致性就消失了,此为AP。
这样的情况下,又有人提出了,如果没有分区不是一直存在不会消失的,那么这个系统就可以做到满足CA,在出现分区的情况下,我们先将数据在各个分区存储起来,待分区消失的时候再进行更新,这样整个服务也是可以接受的,把强一致性替换为了最终一致性。在此基础上出现了BASE理论。
BASE理论
BASE是Basically Available(基本可用),Soft state(软状态),Eventually consistent(最终一致性)三个短语的缩写。是在经历了分布式实践中,由CAP定理演化而来的.
“既是无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。”
基本可用作相应时间和功能上做了妥协,在出现不可预知的故障时,允许服务花费比预计多一些的时间来返回结果,功能上允许在可接受的时间内功能不可用。
软状态允许数据不保持强一致性,但是不影响系统整体的可用性,这样的时候如果数据有延时,数据有错误但是最终可以恢复到正常状态,都是允许的。
最终一直性指的就是在软状态的情况下,数据最终会恢复到一致性的状态。
“系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值。”
2PC
2PC是指两阶段提交(Two-Phase Commit)是人们为了解决分布式的数据一致性问题而提出的。它分为如下几个阶段:
-
准备阶段
- 协调者向所有参与者发送事务内容并询问是否可以提交事务。
- 各个参与者执行操作但不提交事务,将undo和redo信息记入事务日志。
- 如果参与者执行成功,返回给协调者YES,如果失败则返回NO。
-
提交阶段
这个时候如果所有参与者都返回YES,则协调者同意提交事务;如果有参与者返回NO,那么中断事务。
如要提交事务,则进行如下步骤:- 协调者向所有参与者发送正式提交事务请求。
- 参与者执行提交事务请求并释放资源。
- 参与者向协调者反馈ACK消息。
- 协调者受到所有参与者的ACK消息则完成此次事务提交。
如要中断事务,则进行如下步骤:
1. 协调者向所有参与者发送回滚事务请求。
2. 参与者执行回滚操作,并释放资源。
3. 参与者向协调者反馈ACK消息。
4. 协调者受到所有参与者的ACK消息则完成此次事务中断。
2PC 存在的问题是:
- 所有的事务参与者都处于阻塞状态。
- 协调者存在单点问题.
- 如果发生脑裂,则会导致一致性问题。
针对2PC出现的问题,人们进行了改进,由此出现了3PC。
3PC
3PC,三阶段提交协议,将事务的提交过程分为CanCommit、PreCommit、do Commit三个阶段来进行处理。
- CanCommit
- 协调者向所有参与者发出包含事务内容的CanCommit请求,询问是否可以提交事务,并等待所有参与者答复。
- 参与者收到CanCommit请求后,如果认为可以执行事务操作,则反馈YES并进入预备状态,否则反馈NO。
- PreCommit
- 所有参与者均反馈YES,即执行事务预提交。
- 任何一个参与者反馈NO,或者超时,即中断事务。
- 如果执行预提交,会发送预提交消息给各个参与者,参与者执行过之后,记录事务日志,并向协调者发送ACK信息。
- 如果要中断事务,需要向所有参与者发送中断请求,参与者受到请求或者超时都会执行中断请求。
- do Commit
提交事务:
1. 如果协调者处于工作状态,则向所有参与者发出do Commit请求。
2. 参与者收到do Commit请求后,会正式执行事务提交,并释放整个事务期间占用的资源。
3. 各参与者向协调者反馈Ack完成的消息。
4. 协调者收到所有参与者反馈的Ack消息后,即完成事务提交。
中断事务:
1. 如果协调者处于工作状态,向所有参与者发出中断请求。
2. 参与者执行回滚操作,并释放整个事务期间占用的资源。
3. 各参与者向协调者反馈Ack完成的消息。
4. 协调者收到所有参与者反馈的Ack消息后,即完成事务中断。
在阶段3可能出现协调者与参与者无法进行通信的情况,在这个时候参与者在等待超时后,依旧会进行事务提交。
3PC的优点是降低了阻塞范围,单点故障不影响执行,缺点是和2PC一样存在脑裂问题。都无法彻底解决分布式一致性问题。最终,人们有想到了一种方式,就是Paxos。
Paxos
Paxos 算法推理不是很好理解的,这里我们只是简单讲一下流程。
Paxos是Lamport大师假想以希腊城邦Paxos进行选举作为例子,来阐述分布式环境下,通过少数服从多数的方式,最终达成一致意见的算法。这个城邦是采用民主投票的方式进行选举,但是居民们不愿意把全部的精力花在选举上面,因此只能不定时的来参加提议,提出提议,了解投票进展,表达自己对提议的意见(是否赞同)。
这里存在三个主要角色:
Proposer(提案者/提议者):提议一个值,用于被投票决议。用P1,P2等等指代。
Acceptor(附议者/接受者):对每个提议进行投票。用A1,A2等等指代。
Learner(学习者/告知者):被告知投票的结果,不参与投票过程。用L1,L2等等指代。
假设一个提议为[n,v],n为受到的提议编号,v为收到的提议值,规定在收到不同的提议的时候,响应n较为大的提议。n1,n2…依次增大。
首先,P1,P2发送消息给A1,A2,A3。
A1如果先收到P1的[n1,v1]请求,就会响应给P1接受提案且表示之前没有提案,A2如果先收到P1的[n1,v1]请求,也会响应给P1接受提案且表示之前没有提案,A3如果先收到P2的[n2,v2]请求,则会响应给P2接受提案且表示之前没有提案。
A1如果再收到P2的[n2,v2]请求,因为n2>n1,就会响应给P2接受提案,A2如果再收到P2的[n2,v2]请求,因为n2>n1,就会响应给P2接受提案,A3如果再收到P1的[n1,v1]请求,因为n1<n2,因此不会响应n1的提案。
此时P1收到超过一半的响应,就可以向所有的A发送接受此提案的请求,这个请求在此刻是不会被所有的A响应的,因为A已经响应了P2的[n2,v2]请求,并且n2>n1。
此时P2收到超过一半的响应,就可以向所有的A发送接受此提案的请求,此时这个提案会被所有的A所接受,因为当前A或者的提案n的最大值为n2。
当A接收到请求,并且该请求的n大于或等于当前A最新接受的提案的n,那么就A就把此提案发给L,当L发现超过一半的A接受了某个提案,那么这个提案就是最终提案。
上面只包含了Paxos的一种场景,更多的内容等以后继续补充。