1.一致性协议

1.1两阶段提交2PC:

本身是一致强一致性算法,所以很适合用作数据库的分布式事务。其实数据库的经常用到的TCC本身就是一种2PC。

数据库事务:回顾下数据库的事务,对一条数据的修改操作首先写undo日志,记录的数据原来的样子,接下来执行事务修改操作,把数据写到redo日志里面,万一捅娄子,事务失败了,可从undo里面回复数据。

数据库通过undo与redo能保证数据的强一致性,要解决分布式事务的前提就是当个节点是支持事务的。在这个前提下,2PC将整个分布式事务分两节点:

  • 1.第一阶段:为准备节点,事务的请求都发送给一个个资源,资源可以是数据库,也可以是其他支持事务的框架(比如zookeeper),他们会分别执行自己的事务,写日志到undo与redo,但不提交事务。
  • 2.第二阶段:当事务管理器收到了所以资源的反馈,事务都执行没报错后,事务管理器再发送commit指令让资源把事务提交,一旦发现任何一个资源在准备阶段没有执行成功,事务管理器会发送rollback,让所有的资源都回滚。

强一致性是指:保证每个资源都成功,整个分布式事务才成功.

clipboard.png

缺点:

  • 1.同步阻塞.----------所有的节点都在等待其他节点的响应,无法进行其他操作。这种同步阻塞极大的限制了分布式系统的性能。
  • 2.单点问题.----------如果协调者在提交(commit)阶段出现问题,那么整个流程将无法运转。更重要的是,其他参与者将会处于一直锁定事务资源的状态中,而无法继续完成事务操作.
  • 3.数据不一致.-------若协调者即事务管理器未发送完所有commit请求自身崩溃,则导致一部分参与者未收到commit请求,导致数据不一致.
  • 4.容错性不好.----任何一个节点失败都会导致整个事务失败.

1.2.三阶段提交 three-phase commit (3PC)

clipboard.png

  • 第一阶段:协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。
  • 第二阶段:如果所有服务都ok,可以接收事务请求,这一阶段就可以执行事务了,这时候也是每个资源都回写redo与undo日志,事务执行成功,返回ack(yes),否则返回no
  • 第三阶段:这阶段和前面说的2阶段提交大同小异,这个时候协调者发现所有提交者事务提交者事务都正常执行后,给所有资源发送commit指令。

与2PC区别:
第二阶段才写undo和redo事务日志
第三阶段协调者出现异常或网络超时参与者也会commit

三阶段3PC优点:
相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,比如由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。


但回顾整个过程,不管是2pc,还是3pc,同步阻塞,单点故障,容错机制不完善这些问题都没本质上得到解决,尤其是前面说得数据一致性问题,反而更糟糕了。

所有数据库的分布式事务一般都是二阶段提交,而者三阶段的思想更多的被借鉴扩散成其他的算法


1.3.Paxos算法

clipboard.png

paxos算法分为两个阶段,有2个角色,提议者和接受者。

关键是:
1.少数服从多数
2.角色轮换避免单点故障
具体流程也没搞清楚~~先知道核心思想即可


2 zookeeper集群

2.1 zookeeper集群特点

clipboard.png

  • 顺序一致性 :客户端的更新顺序与它们被发送的顺序相一致。
  • 原子性: 更新操作要么成功要么失败,没有第三种结果。
  • 单一视图: 无论客户端连接到哪一个服务器,客户端将看到相同的 ZooKeeper 视图。
  • 可靠性: 一旦一个更新操作被应用,那么在客户端再次更新它之前,它的值将不会改变。
  • 实时性: 连接上一个服务端数据修改,所以其他的服务端都会实时的跟新,不算完全的实时,有一点延时的
  • 角色轮换避免单点故障: 当leader出现问题的时候,会选举从follower中选举一个新的leader

集群中的角色

  • Leader: 集群工作机制中的核心 事务请求的唯一调度和处理者,保证集群事务处理的顺序性,
    集群内部个服务器的调度者(管理follower,数据同步)
  • Follower: 集群工作机制中的跟随者处理非事务请求,转发事务请求给Leader, 参与事务请求proposal投票, 参与leader选举投票
  • Observer: 观察者 3.30以上版本提供,和follower功能相同,但不参与任何形式投票 处理非事务请求,转发事务请求给Leader 提高集群非事务处理能力

2.1 zookeeper集群搭建

1.安装JDK,zookeeper。

2.配置环境变量
vi /etc/profile

export JAVA_HOME=/usr/local/jdk1.8.0_211
export ZOOKEEPER_HOME=/usr/local/zookeeper
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin:$PATH

刷新profile文件
source /etc/profile

关闭防火墙(命令视不同系统情况而定)

3.修改zk配置文件

mv zoo_sample.cfg zoo.cfg

修改conf: vi zoo.cfg 修改两处
(1) dataDir=/usr/local/zookeeper/data(注意同时在zookeeper创建data目录)

  dataDirLog=/usr/local/zookeeper/log  日志目录,并创建目录

(2)最后面添加
server.0=192.168.64.128:2888:3888(2888是集群内机器通讯端口,3888是选举leader使用)
server.1=192.168.64.129:2888:3888
server.2=192.168.64.130:2888:3888

注意:server.0,server.1中,0和1就是服务器标识
4.创建服务器标识

在dataDir路径下data目录下创建myid文件,内容即为0/1/2,即上述配置的。

5.复制 /usr/local/zookeeper下所有文件到另外2个服务器上面,只修改myid的服务器标识即可。

启动三台机器的zk,./zkServer.sh start
./zkServer.sh start查看状态即可查看角色是leader还是follower。
启动失败的时候查看bin目录下zookeeper.out日志


2.2 Zookeeper集群一致性协议ZAB

zab其实是paxos的一个简化实现。zookeeper就是根据zab协议建立了主备模型完成集群的数据同步(保证数据的一致性).

zab协议是分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性。


zab协议核心:

整个zookeeper集群中只有一个节点leader将所有客户端的写操作转化为事务(提议proposal).leader节点在数据写完之后,将向所有的follower节点发送数据广播请求(数据复制),等所有的follower节点的反馈,在zab协议中,只要超过半数follower节点反馈ok,leader节点会向所有follower服务器发送commit消息,既将leader节点上的数据同步到follower节点之上

clipboard.png


ZAB协议两种模式:消息广播和崩溃恢复

消息广播:

  1. Leader 接收到消息请求后,将消息赋予一个全局唯一的 64 位自增 id,叫做:zxid。
  2. Leader 通过先进先出队列(通过 TCP 协议来实现,以此实现了全局有序这一特性)将带有zxid的消息作为一个提案(proposal)分发给所有 follower。
  3. 当 follower 接收到 proposal,先将 proposal写到硬盘(事务日志),写硬盘成功后再向 leader回一个ACK。
  4. 当 leader 接收到合法数量的 ACKs 后,leader 就向所有 follower 发送 COMMIT命令,会在本地执行该消息。
  5. 当 follower收到消息的 COMMIT 命令时,就会执行该消息

为了进一步防止阻塞,leader服务器与每个follower之间都有一个单独的队列进行收发消息,使用队列消息可以做到异步解耦。leader和follower之间只要往队列中发送了消息即可。如果使用同步方式容易引起阻塞。性能上要下降很多


崩溃恢复:tips:集群机器的数量必须是奇数

zookeeper集群中为保证任何所有进程能够有序的顺序执行,只能是leader服务器接受写请求,即使是follower服务器接受到客户端的请求,也会转发到leader服务器进行处理。

如果leader服务器发生崩溃(重启是一种特殊的奔溃,这时候也没leader),则zab协议要求zookeeper集群进行崩溃恢复和leader服务器选举。

  1. 每个Server会发出一个投票,第一次都是投自己。投票信息:(myid,ZXID)
  2. 收集来自各个服务器的投票
  3. 处理投票并重新投票,处理逻辑:优先比较ZXID,然后比较myid
  4. 统计投票,只要超过半数的机器接收到同样的投票信息,就可以确定leader
  5. 改变服务器状态

新选举出来的leader不能包含未提交的proposal(事务),即新选举的leader必须都是已经提交了的proposal的follower服务器节点。同时,新选举的leader节点中含有最高的ZXID。这样做的好处就是可以避免了leader服务器检查proposal的提交和丢弃工作。

这也是为什么优先选择大的zxid的原因。


2.3 Java客户端连接集群

把连接地址用逗号分隔就好,包括Ip和端口
ZkClient client = new ZkClient("host1,host2,host3,host4,host5");


y猪
246 声望25 粉丝