分布式,集群,单点问题
与分布式相对应的就是单机的概念。
比如一个服务,依赖nginx
,tomcat
,mysql
,redis
这么多组件。
单机的话可能就部署在一个服务器上。
这样的话容易服务器挂了,整个服务就不可用了。
同时可扩展性不是很好,一台普通的机器用来跑简单的服务还是可以的,万一是个需要高并发的,数据量比较大的呢,那就只能去买大型机了,但是大型机价格昂贵。同时还是避免不了如果机器挂了,整个服务就不可用的问题。
好,那我们从单机的状态下转移出来
现在我们Redis
,Tomcat
,Mysql
,Nginx
都是单独在一台服务器上。
那么整个服务就可以称为是分布式的。
那么集群是怎么回事呢?
就比如跑Nginx
这个服务器挂了,Nginx
也就挂了,那么即使Mysql
没挂,整个服务还是不能正常运行。
这个Nginx
服务器就是个单点问题。
所以即使把服务都分开部署,还是无法解决不可用的问题,那么怎么提高服务的可用性呢。
那就是使用集群了。
我们部署三个机器都是跑Nginx
,那么一台挂了不至于导致整个服务不可用。
当然Nginx
一般来说是无状态的,如果整个集群是有状态的呢。
那就需要一些一致性协议来进行实现。
真正做起来还是比较复杂的。
CAP
CAP理论由Eric Brewer教授在2000年提出的
主要说明了一点,在一个分布式环境中
Consistency一致性、Availability可用性、Partition-tolerance分区容错性
这三个条件不能同时满足,最多只能满足其中的两个。
其实我们在仔细斟酌下,按照我的理解,其实这个是针对集群的,比如Zookeeper集群,称为是分布式环境中的其实不太准确。
再而这个针对的是什么集群呢,nginx集群吗,显然不是,看第一条,一致性,nginx需要什么一致性?那么在仔细想下,这个理论应该是针对提供数据相关功能的服务的。比如数据库之类。
从上图我们可以看到,一个服务最多满足CAP
中的两个而放弃另外一个,像Redis
放弃了可用性,选择了一致性和分区容错性。当然这是单机的Redis。
那么这三个条件具体是什么意思呢
一致性 简单的说,同样的数据在多个集群的所有机器上是否是一样的
或者这么说,同一个请求在一个集群中所有的机器上的结果应当是一样的。不允许出现不一样的状态。可用性 整个集群对于别的服务的请求必须在有限时间内返回结果。
分区容错性 这个比较难理解,首先什么是分区呢,正常来说,整个集群应该是一个整体,每台机器可以通过网络互相沟通,但是可能因为网络分区的原因,出现了两个分区,每个分区的机器都可以互相沟通,但是跨分区的机器不能沟通。
如果数据项只在一个节点中,那么分区出现后,和这个节点之前连通的部分就访问不到这个数据了,那么这就是分区不容忍的。
提高分区容忍性的办法就是一个数据项复制到多个节点上,那么出现分区之后,这一数据项就可能分布到各个区里。容忍性就提高了。
然而,要把数据复制到多个节点,就会带来一致性的问题,就是多个节点上面的数据可能是不一致的。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。
所以正常情况下,分布式系统中,都要满足分区容错性,然后在一致性和可用性之间做出权衡。
BASE
BASE理论在CAP提出之后,因为CAP提出三个条件,提供数据服务的集群最多保证其中两个。
同时一般来说我们P是不可能放弃的,基本都是在C和A之间权衡。
那么具体怎么权衡呢,BASE就是一种讨论的结果。
BASE是Basically Available, Soft state, Eventually consistent三个短语的缩写。
也就是基本可用,软状态,最终一致性。
基本可用
基本可用不代表不可用,而是在一些情况下在高可用上有稍许的宽松
比较典型的就是
- 响应时间上的损失
- 功能上的损失,降级等。
弱状态
允许系统出现中间状态
即允许数据同步的过程中存在延迟
最终一致性
强一致性的条件比较严格,就比如我提出了一个写请求,那么我写完之后,必须保证每个机器上都能得到体现,数据必须是一样的。这是强一致性。
最终一致性就是允许中间有延迟时间,但是保证一定会达到一致,至于多久,这个并没有严格的限制。
2PC
2PC => Two Phase Commitment Protocol
也就是二阶段提交协议
在分布式事务中,事务协调器和资源管理器进行事务的过程。
第一阶段
TM像所有的RM发送prepare指令,相当于执行start transection并执行sql语句,但是并不提交。
RM执行完之后会向TM发送反馈。
第二阶段
接收完RM的反馈后,如果有返回NO的,那么TM向所有的RM发送abort指令,放弃事务提交
如果反馈全是Yes,那么发送commit指令。
整个过程很简单,各个书上对这个过程的描述也是一致的。
3PC
由2PC的名字可以联想到,其实这个是三阶段提交协议的意思
三阶段提交协议主要把2PC的第二阶段拆分为两个阶段 preCommit和doCommit阶段
2PC和3PC对比
首先对一下细节的探究。
2PC中TM有主备机制吗?
这个问题困扰了我很久,最后得到的结论是没有的,只有一个TM,挂了就全局阻塞。
参见文章链接
文章的3.3节中提到They have usually attempted to “fix” the Two-Phase Commit protocol by
choosing another TM if the first TM fails.2PC中如果TM挂了,那么RM有超时机制吗
从众多描述中可以发现是没有的
参见问题
链接1
链接2
注意这种情况是TM挂了的情况,如果是RM挂了,TM是可以具有超时abort机制的。2PC的数据不一致的情况
链接2PC协议中,如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。
这里解释一下他说的不一致是什么情景,就是协调者进入第二阶段,发送Commit请求了,当发给第一个RM时挂了,第一个RM收到请求,Commit后也挂了。
但是如果这么想的话,因为RM没有超时机制,下面就只有等TM被repair,这时候其实并不是严格处于一个数据不一致的状态。
- 3PC怎么解决这么问题的
其实仔细看的话,3PC确实解决了一些问题,但是3PC本身还是有问题的。- 引入RM超时机制,如果发出canCommit后TM挂了,那么RM超时后会自动取消事务,同样的,如果preCommit后TM挂了,那么RM超时后会自动提交事务,一部分情况下避免了无线阻塞。
- 引入TM重新选举
但是3PC解决了2PC的问题了吗,阻塞问题算了解决了一下,但是数据不一致的问题确实依然存在的。
加入TM发出一个preCommit后挂了,然后一个RM接收到preCommit,其他的没接收到,超时后其他的abort了,只有一个commit了,那么数据不一致还是存在的,而且似乎更严重了一些。
下面是一些资料:
摘自维基百科 链接
The greatest disadvantage of the two-phase commit protocol is that it is a blocking protocol. If the coordinator fails permanently, some cohorts will never resolve their transactions: After a cohort has sent an agreement message to the coordinator, it will block until a commit or rollback is received.
A two-phase commit protocol cannot dependably recover from a failure of both the coordinator and a cohort member during the Commit phase. If only the coordinator had failed, and no cohort members had received a commit message, it could safely be inferred that no commit had happened. If, however, both the coordinator and a cohort member failed, it is possible that the failed cohort member was the first to be notified, and had actually done the commit. Even if a new coordinator is selected, it cannot confidently proceed with the operation until it has received an agreement from all cohort members, and hence must block until all cohort members respond.
2PC协议中,如果出现协调者和参与者都挂了的情况,有可能导致数据不一致。
这里解释一下他说的不一致是什么情景,就是协调者进入第二阶段,发送Commit请求了,当发给第一个RM时挂了,第一个RM收到请求,Commit后也挂了。
Blocking: The Two-Phase Commit Protocol goes to a
blocking state by the failure of the coordinator when the
participants are in uncertain state. The participants keep
locks on resources until they receive the next message
from the coordinator after its recovery.
In a transaction commit protocol, if one or more RMs fail, the transaction
is usually aborted. For example, in the Two-Phase Commit protocol, if the
TM does not receive a Prepared message from some RM soon enough after
sending the Prepare message, then it will abort the transaction by sending
Abort messages to the other RMs. However, the failure of the TM can cause
the protocol to block until the TM is repaired. In particular, if the TM fails
right after every RM has sent a Prepared message, then the other RMs have
no way of knowing whether the TM committed or aborted the transaction.
总结一下,主要还是两个问题
- 阻塞问题
- 数据不一致问题
但是优点也是显而易见的 - 容易实现
XA协议
XA是一个分布式事务的规范,由X/Open组织提出的。
X/Open组织定义了分布式事务处理模型 -> X/Open DTP模型。
在DTP模型中定义了三个组件
- Application Program (AP),应用程序,使用DTP模型的程序
- Resource Manager (RM),资源管理器,可以理解未一个DBMS系统,或者消息服务器管理系统,应用程序通过资源管理器对资源进行控制,资源必须实现XA定义的接口。
- Transaction Manager(TM),事务管理器,负责协调和管理事务,提供给AP应用程序变成接口并管理资源管理器。事务管理器向事务指定标识,监视它们的进程,并负责处理事务的完成和失败。
一个例子:
- AP与RM之间,可以使用RM自身提供的native API进行交互,这种方式就是使用RM的传统方式,并且这个交互不在TM的管理范围内,另外,当AP和RM之间需要进行分布式事务的时候,AP需要得到对RM的链接(此链接由TM管理),然后使用XA的native API来进行交互。
- AP和TM之间,该例子中使用的是TX接口,也是由X/Open所规范的。它用于对事务进行控制,包括事务启动,提交事务和回滚事务。
- TM与RM之间是通过XA接口进行交互。TM管理了到RM的连接,并实现了两阶段提交。
总结:2PC和3PC一定程度上其实是实现了XA协议的。
Paxos
Paxos和2PC
上文提到了数据服务集群的一致性问题,那么怎么保证数据的强一致性呢。
这里就需要用到Paxos算法。
很多人会认为2PC和Paxos解决了同样的问题,Paxos更为先进,可以放弃2PC了。
但是这个其实也是不准确的。
因为2PC和Paxos本质上解决的不是同一个问题。
2PC是为了分布式事务,Paxos是维持多个副本之间的数据一致。
Raft和Zab
Raft和Zab也是一致性算法。
上文说我们已经有了Paxos,那么为什么还提出Raft和Zab呢,因为Paxos的理解较为复杂,也没有提出技术细节的解决方案,较为理论,虽然解决的一致性问题很通用,对于一些细节的阐述不是很清晰。
为了需要一个能实现的算法,于是有了Raft和Zab。
Raft和Zab的区别其实不是很大,Zab主要是用在Zookeeper上。
下面主要说说Raft协议。
参考
CAP部分的分区容错性 =>
https://www.zhihu.com/question/54105974/answer/139037688BASE部分参考=> 《从Paxos到Zookeeper,分布式一致性原理与实践》
XA协议部分参考=> 《大型网站系统与JAVA中间件实践》
课外阅读
https://martin.kleppmann.com/2015/05/11/please-stop-calling-databases-cp-or-ap.html