2PC
翻译过来叫两阶段提交算法,它本身是一致强一致性算法,所以很适合用作数据库的分布式事务。其实数据库的经常用到的TCC本身就是一种2PC.
首先第一阶段叫准备节点,事务管理器把事务的请求都发送给一个个的资源,这里的资源可以是数据库,也可以是其他支持事务的框架,他们会分别执行自己的事务,但是不提交!!!
二阶段当事务管理器收到了所以资源的反馈,事务都执行没报错后,事务管理器再发送commit指令让资源把事务提交,一旦发现任何一个资源在准备阶段没有执行成功(这个发现是指,一阶段的每个资源的反馈是否全部都执行了(比如写操作每个资源即每台机器是否都更新了)!!!),事务管理器会发送rollback,让所有的资源都回滚。这就是2pc,非常非常简单。
优点:原理简单,实现方便
缺点:1 同步阻塞 (在二阶段提交的过程中,所有的节点都在等待其他节点的响应给事务管理器反馈完在进行下一步操作,所以在未反馈完大家无法进行其他操作),
2单点问题(事务管理器挂了),
3数据不一致(发了commit 命令后因为网络原因只有部门资源接收到),
4容错性不好(众多的资源中有一个节点失败就整个事务失败,这真是强一致性啊)
3pc
一阶段:确认所有的资源是否都是健康、在线的,(为了排除一些早就已经挂掉或者宕机无法响应的资源,如果大家都健康在线在执行二阶段,因为二阶段是要干活的,这样如果人都不齐就别干了,减少了当有不在线的资源时,其他资源又要去执行二阶段的事务)【这仅仅解决了2pc 同步阻塞缺点的一种情形,比如比如大家的确都健康,但是不巧的是在二阶段时某个资源在返回由于网络原因,它就是返不回给事务管理器,这还是在阻塞啊】
二阶段:如果所有服务都ok,可以接收事务请求 这与2pc 的一阶段一模一样。
三阶段:与2pc 相同的是 所有资源都反馈操作成功,并且只差提交了,则发commit的指令让大家提交,但是不同的是,如果这时事务管理器挂了,不能发出commit指令时,所有的资源也会默认提交,这主要是解决了2pc 单点问题(但是有没有觉得数据一致性更差了,因为如果事务管理器仅仅是网络原因发布出去,而它本来是想发 rollback的,结果大家都默认了commit!!)
但回顾整个过程,不管是2pc,还是3pc,同步阻塞,单点故障,容错机制不完善这些问题都没本质上得到解决
Paxos算法
paxos算法也分成两阶段。首先这个图有2个角色,提议者与接收者
一阶段:提议者首先提一个协议编号 例如是001,接收者的数量相当于总数量的一般以上则进行第二阶段(这注意这里不在需要所有人都同意了,)【注意这里如果小于一半,则重新发起一个协议编号,并且编号是递增的例如002,然后又被拒接003】[注意:这里的协议编号,本质是确保节点的参与程度,或者说健康度]
二阶段:大家再次投票这个协议的内容,大家是否赞同然后投票还是少数服从多数的投票。【这里大家也可以小于一半,但就要从一阶段从新来过。】【这里的协议内容:本质是说具体的业务,例如对所有参与者发问,我想更新xx的数据,或者删除xx的数据,或者我想干什么什么事,大家来投票行不行,投票过半就是行】
协议要求:如果接收者没有收到过提案编号,他必须接受第一个提案编号
如果接收者没有收到过其他协议,他必须接受第一个协议。
注意:提议者不仅仅只有一个,当有多个,比如两个提议者他们都要问接受者同意吗,在接阶段他们都可以进行,比如两个协议编号大家都通过,但是到了二阶段真正要完成时,议题是先入为主的,谁先占了先机,后面的proposer在第一阶段就会学习到这个议题而修改自己本身的议题,即其他议题会修改去符合,先入主的议题。
zab 协议
zab协议核心是在整个zookeeper集群中只有一个节点既leader将所有客户端的写操作转化为事务(提议proposal).leader节点再数据写完之后,将向所有的follower节点发送数据广播请求(数据复制),等所有的follower节点的反馈,在zab协议中,只要超过半数follower节点反馈ok,leader节点会向所有follower服务器发送commit消息,既将leader节点上的数据同步到follower节点之上。
注意这里的ack 与2pc 的一阶段每个资源完成操作成功后的一个ok 肯定的答复。
【自我总结:一阶段:我(leader即事务管理器)有写操作请求事务,大家都来复制下,并得到了一半以上人的反馈我已经复制完了。二阶段:都给我提交】
Zab再细看可以分成两部分。
第一的消息广播模式,第二是崩溃恢复模式。
zookeeper中消息广播的具体步骤如下:
第一的消息广播模式
1. 客户端发起一个写操作请求
2. Leader服务器将客户端的request请求转化为事物proposql提案,同时为每个proposal分配一个全局唯一的ID,即ZXID。
3. leader服务器与每个follower之间都有一个队列,leader将消息发送到该队列
4. follower机器从队列中取出消息处理完(写入本地事物日志中)毕后,向leader服务器发送ACK确认。
5. leader服务器收到半数以上的follower的ACK后,即认为可以发送commit
6. leader向所有的follower服务器发送commit消息。
为了进一步防止阻塞,leader服务器与每个follower之间都有一个单独的队列进行收发消息,使用队列消息可以做到异步解耦。leader和follower之间只要往队列中发送了消息即可。如果使用同步方式容易引起阻塞。性能上要下降很多
二是崩溃恢复模式。
ZAB协议崩溃恢复要求满足如下2个要求:
确保已经被leader提交的proposal必须最终被所有的follower服务器提交。
确保丢弃已经被leader出的但是没有被提交的proposal。
新选举出来的leader不能包含未提交的proposal,即新选举的leader必须都是已经提交了的proposal的follower服务器节点。同时,新选举的leader节点中含有最高的ZXID。这样做的好处就是可以避免了leader服务器检查proposal的提交和丢弃工作。
- 每个Server会发出一个投票,第一次都是投自己。投票信息:(myid,ZXID)
- 收集来自各个服务器的投票
- 处理投票并重新投票,处理逻辑:优先比较ZXID,然后比较myid
- 统计投票,只要超过半数的机器接收到同样的投票信息,就可以确定leader
- 改变服务器状态