java
怎么保证任务只在一个节点执行redis
若是orderserver1挂了,其余节点如何发现并接替算法
存在共享资源,互斥性、安全性apache
api
Google 的Chubby 是一个分布式锁服务,经过Google Chubby 来解决分布式协做、Master选举等与分布式锁服务相关的问题安全
服务器
集群方案(Leader Follower)还能分担请求,既作了高可用,又作高性能架构
每一个节点的数据是一致的(必需要有leader)分布式
leader master(带中心化的) redis-cluser (无中心化的)性能
集群中的leader 挂了,怎么办?数据怎么恢复?
选举机制?数据恢复
如何去保证数据一致性?(分布式事务)
2PC 协议、二阶提交
事务询问
协调者向全部的参与者发送事务内容,询问是否能够执行事务提交操做,并开始等待各参与者的响应。
执行事务
各个参与者节点执行事务操做,并将Undo和Redo信息记录到事务日志中,尽可能把提交过程当中全部消耗时间的操做和准备的提早完成确保后面100%成功提交事务
各个参与者向协调者反馈事务询问的响应
若是各个参与者都成功执行了事务操做,那么就反馈给参与者yes的响应,表示事务能够执行;
若是参与者没有成功执行事务,就反馈给协调者no的响应,表示事务不能够执行;
2pc 协议的第一个阶段称为“投票阶段”,即各参与者投票表名是否须要继续执行接下去的事务提交操做。
在这个阶段,协调者会根据各参与者的反馈状况来决定最终是否能够进行事务提交操做;
两种可能:
执行事务
中断事务
若是是读请求,就直接从当前节点中读取数据
若是是写请求,那么请求会转发给leader 提交事务,而后leader将事务广播给集群中的follower节点(注意obeserver节点不参与投票),Follower 节点给leader 一个ack (ack表示当前的节点是否是能执行这个事务),只要有超过半数节点写入成功,那么写请求就会被提交。集群节点须要(2n+1)
是zookeeper中的整个核心,起到了主导整个集群的做用
事务请求的调度和处理
保证事务处理的顺序性
处理客户端的非事务请求,
转发事务请求给leader服务器
参与事务请求Proposal 的投票(须要半数以上服务器经过才能通知leader commit数据; Leader发起的提案, 要求Follower投票)
参与leader节点选举的投票
是一个观察者角色
了解集群中的状态变化 ,和对这些状态进行同步
工做原理和follower节点同样,惟一差异是不参与事务请求的投票,不参与Leader选举
Observer 只提供非事务请求,一般在于不影响集群事务处理能力的前提下,提高集群非事务处理能力
注:
表示奇数节点, zookeeper中要正常对外提供服务的话,它里面有个投票机制,这个机制就是必需要有过半的机器正常工做,而且可以彼此完成通讯进行事务投票结果。
支持崩溃恢复的原子广播协议,主要用于数据一致性
ZAB协议基本模式
崩溃恢复(恢复leader节点和恢复数据)
原子广播
消息广播过程实际是一个简化版的二阶提交。2PC
leader 接收到消息请求后,将消息赋予一个全局惟一的64位自增id(ZXID)。ZXID大小,实现因果有序的特征。
leader 为每个follower 准备了一个FIFO队列,将带有zxid的消息做为一个提案(Proposal)分发给全部follower
当follower 收到proposal,先把proposal写到磁盘,写入成功后,再向leader 回复一个ack
当leader接收到合法数量的ack后,leader 就会向这个follower 发送commit命令,同时会在本地执行该消息。
当follower 收到消息的commit之后,会提交该消息。
注:leader 的投票过程,不须要Observer 的ack,可是Observer必需要同步Leader的数据,保证数据的一致性。
当leader服务器宕机
集群进去崩溃恢复阶段
对于数据恢复来讲
已经处理的消息不能丢失
当leader 收到合法数量的follower 的ack之后,就会向各个follower 广播消息(commit命令),同时本身也会commit 这条事务消息。
若是follower节点收到commit命令以前,leader挂了,会致使部分节点收到commit,部分节点没有收到。
ZAB协议须要保证已经处理的消息不能丢失。
被丢弃的消息不能再次出现
当Leader收到事务请求,还未发起事务投票以前,leader挂了
ZAB的设计思想
zxid 是最大的
若是leader选举算法可以保证新选举出来的leader服务器拥有集群中全部机器最高编号(ZXID最大)的事务Proposal,那么就能够保证这个新选举出来的Leader必定具备已经提交的提案。由于全部提案被Commit以前必须有超过半数的Follower ACK,即必须有超过半数的服务器的事务日志上有该提案的proposal,所以,只要有合法数量的节点正常工做,就必然有一个节点保存了全部被commit消息的proposal状态。
epoch的概念,每产生一个新的leader,那么新的leader的epoch会+1,zxid 是64位的数据,低32位表示消息计数器(自增),每收到一条消息,这个值+1,新 leader选举后这个值重置为0。这样设计的缘由在于,老的leader 挂了之后重启,他不会选举为leader,y所以此时它的zxid确定小于当前新的leader.当老的 leader 做为 follower 接入新的 leader 后,新的 leader会让它将全部的拥有旧的epoch号的未被COMMIT的proposal清除 .高32位会存储epoch编号
为了保证事务顺序的一致性,Zookeeper 采用了递增的事务id号来标识事务。
全部的提议Proposal都在被提出的时候加上了zxid.
ZXID 是一个64位的数字(低32位和高32位组成)
低32位:表示消息计数器
高32位 :表示epoch,用来标识 leader 关系是否改变。 每次一个leader被选出来,都会有一个新的epoch(原来的epoch+1),标识当前属于那个leader的统治时期。
注:
leader: 相似,有本身的年号,每次变动都会在前一个年代上加1。
/tmp/zookeeper/VERSION-2 路径会看到一个 currentEpoch文件。文件显示的是当前的epoch
经过命令查看事务日志
java -cp :/opt/zookeeper/zookeeper-3.4.10/lib/slf4j-api-1.6.1.jar:/opt/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.jar org.apache.zookeeper.server.LogFormatter /tmp/zookeeper/version-2/log.100000001
注:
ZXID(事务ID)事务ID 越大,那么表示数据越新, 最大会设置为Leader, ,
epoch ,每一轮投票,epoch 都会递增
myid (服务器id ,server id)
myid 越大,在leader 选举机制中权重越大
服务启动时的状态都是LOOKING,观望状态
LEADING
FOLLOWING
OBSERVING
投票信息包含(myid,zxid,epoch)
接受来自各个服务器的投票
判断该投票是否有效
检查是否来自本轮投票epoch
检查是否来时LOOKING状态的服务器
处理投票
检查ZXID,若是ZXID比较大,那么设置为Leader,
若是ZXID相同,会检查myid,myid比较大的,设置为leader
统计投票
判断是否已经有过半机器接受到相同的投票信息
若是有过半机器接受,便认为已经选举出了Leader
改变服务器状态
若是是Follower,那么状态变为FOLLOWING
若是是Leader,那么状态变为LEADING
变动状态
Leader 挂后,余下非Observer服务器都会将本身的服务器状态变为LOOKING,
开始进入Leader选举过程
每一个Server会发起一个投票。
运行期间,ZXID 可能不一样,而后将各自的投票发送给集群中的全部机器。
其他与启动时过程相同。