本文主要对zk的集群特性、一致性机制、选举机制进行简单分析。
一、zookeeper集群
配置多个实例共同构成一个集群对外提供服务以达到水平扩展的目的,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。
1.1、集群中的角色
Leader - 集群工作机制中的核心
1、事务请求的唯一调度和处理者, 保证集群事务处理的顺序性
2、集群内部个服务器的调度者(管理 follower,数据同步)
Follower - 集群工作机制中的跟随者
1. 处理客户端非事物请求、转发事物请求给 leader 服务器
2. 参与事物请求 Proposal 的投票(需要半数以上服务器通过才能通知 leader commit 数据;Leader 发起的提案,要求 Follower 投票)
3. 参与 Leader 选举的投票
Observer - 观察者
3.30 以上版本提供, 和 follower 功能相同, 但不参与任何形式投票
处理非事务请求, 转发事务请求给 Leader
提高集群非事务处理能力
1.2、zk集群的特点
- 顺序一致性
客户端的更新顺序与它们被发送的顺序相一致。 - 原子性
更新操作要么成功要么失败,没有第三种结果。 - 单一视图
无论客户端连接到哪一个服务器,客户端将看到相同的 ZooKeeper 视图。 - 可靠性
一旦一个更新操作被应用,那么在客户端再次更新它之前,它的值将不会改变。 - 实时性
连接上一个服务端数据修改,所以其他的服务端都会实时的跟新,不算完全的实时,有一点延时的 - 角色轮换避免单点故障
当leader出现问题的时候,会选举从follower中选举一个新的leader
二、一致性协议
2.1、一致性协议概述
2.1.1、两阶段提交 two-phase commit (2PC)
首先来看下2PC,翻译过来叫两阶段提交算法,它本身是一致强一致性算法,所以很适合用作数据库的分布式事务。其实数据库的经常用到的TCC本身就是一种2PC.
回想下数据库的事务,数据库不管是MySQL还是MSSql,本身都提供的很完善的事务支持。
MySQL后面学分表分库的时候会讲到在innodb存储引擎,对数据库的修改都会写到undo和redo中,不只是数据库,很多需要事务支持的都会用到这个思路。
对一条数据的修改操作首先写undo日志,记录的数据原来的样子,接下来执行事务修改操作,把数据写到redo日志里面,万一捅娄子,事务失败了,可从undo里面回复数据。
不只是数据库,在很多企业里面,比如华为等提交数据库修改都回要求这样,你要新增一个字段,首先要把修改数据库的字段SQL提交给DBA(redo),这不够,还需要把删除你提交字段,把数据还原成你修改之前的语句也一并提交者叫(undo)
数据库通过undo与redo能保证数据的强一致性,要解决分布式事务的前提就是当个节点是支持事务的。
这在个前提下,2pc借鉴这失效,首先把整个分布式事务分两节点,首先第一阶段叫准备节点,事务的请求都发送给一个个的资源,这里的资源可以是数据库,也可以是其他支持事务的框架,他们会分别执行自己的事务,写日志到undo与redo,但是不提交事务。
当事务管理器收到了所以资源的反馈,事务都执行没报错后,事务管理器再发送commit指令让资源把事务提交,一旦发现任何一个资源在准备阶段没有执行成功,事务管理器会发送rollback,让所有的资源都回滚。这就是2pc,非常简单。
准备阶段
事务的请求都发送给一个个的资源,这里的资源可以是数据库,也可以是其他支持事务的框架,他们会分别执行自己的事务,写日志到undo与redo,但是不提交事务。
提交阶段
当事务管理器收到了所以资源的反馈,事务都执行没报错后,事务管理器再发送commit指令让资源把事务提交,一旦发现任何一个资源在准备阶段没有执行成功,事务管理器会发送rollback,让所有的资源都回滚。
2.1.2、三阶段提交 three-phase commit (3PC)
第一阶段canCommit
确认所有的资源是否都是健康、在线的,以约女孩举例,你会打个电话问下她是不是在家,而且可以约个会。
如果女孩有空,你在去约她。
就因为有了这一阶段,大大的减少了2段提交的阻塞时间,在2段提交,如果有3个数据库,恰恰第三个数据库出现问题,其他两个都会执行耗费时间的事务操作,到第三个却发现连接不上。3段优化了这种情况
第二阶段PreCommit
如果所有服务都ok,可以接收事务请求,这一阶段就可以执行事务了,这时候也是每个资源都回写redo与undo日志,事务执行成功,返回ack(yes),否则返回no