Zookeeper初始(一)--未完待续

ZK是什么?

分布式服务框架,主要用来解决分布式应用中数据管理问题;如统一命名服务,集群管理,分布式应用配置管理等

zk是一个数据库,是一个拥有文件系统特点的数据库

是一个 解决了数据一致性问题的分布式数据库

是一个具有发布,订阅(watch)功能的分布式数据库

集群何时选取Leader?

  1. 集群启动时选择Leader(服务器启动)
  2. Leader挂掉时选举
  3. follower挂掉后Leader发现没有过半follower跟随自己-不能对外提供服务(领导者选举)

如何选举?

投票->改票->选票

zxid相同怎办?
相同不在选举,如上图加入zk3的zxid为10 则不再进行选举直接zk2为Leader;
 
初始启动,没有zxid?
没有事务ID,使用myid进行选举myid最大的为Leader(myid每台服务器不一样,一样会报错,启动不起来);
 
总结:启动选举Leader
1.节点事务ID相同或者没有事务ID——根据myid选举
2.选择事务ID大的
3.如果已经选举到Leader,此时有加入一个相同事务ID的节点,不做选举直接加入,使用已经选择的Leader
4.如果已经选举到Leader,此时有加入一个大于事务ID的节点?分析为什么会有大的事物ID加入,所有事务请求Leader节点处理?不明白?
 

 

一致性?2PC机制,zk是保证CP

弱一致

强一致

最终一致

 

如何解决一致性问题?2PC机制

 事务请求:事务性请求:create ,set ,deLete,update, 生成事务日志,zxid(自增的)

  1. 预提交占用follower资源(占用资源:其实是在follower节点上面写一条事务日志,事务日志先持久化到硬盘)
  2. 接收到大于一半的ack
  3. 提交:将磁盘内容读更新到内存的DataTree

事务请求,Leader 接受请求,然后将数据同步给其他节点,如果同步过程中异常,有一半(3个节点, 有一个成功)其他都异常则回滚改该请求,少于一半(3个节点, 有两个成功)则提交事务,整个集群挂掉,再次启动的时候 会主动同步数据

非事务性请求:get,exists,读请求是直接返回本节点数据  

数据同步?启动时候同步数据

ZAB协议? 保证一致性

就是规定:如何领导选举,过半机制, 2pc的内容如何提交,数据同步等

  

问题?

过半机制当有一台已经收到ack ,另外响应慢怎么办?过一半提交, 少于一半则回滚

当提交的时候是所有Folower都提交之后,Leader才提交吗?

 Leader会把要发送的数据放到队列里面,循环follower节点从队列里面获取数据发送(线程异步发送),然后提交自己节点数据包,如果follower节点发送比较慢,不会影响最终Leader响应用户的速度(不会等待所有follower节点都执行成功,follower节点是异步执行的)

查看谁是Leader? status

为什么是 >n/2 而不是>=haLf ? 担心有两个Leader  

zk 保证的是CP机制 

为什么是推荐奇数节点?过半机制

 5 台机器可以有2台挂掉

 6台机器也可以有2台挂掉 那为什么要用6台呢?

zk有哪些节点:

  •    Leader节点
  •    follower机器越多:提高读性能,降低写性能(第一:选举Leader,每多一个follower都需要投票 ,第二:每个follower都需要发送ack请求)那怎么提高性能?使用观察者节点
  •    观察者节点(obser):可以处理读写请求(写请求转发给Leader,读请求直接返回本节点数据),不参与Leader选举投票,提高读请求,不影响写请求性能

Leader是如何提交的,即如何submit?

  1.  发送follower提交请求(事务ID)将数据包发入到队列里面,有单独线程发送submit请求给follower
  2.  同步信息给观察者节点(是直接发送数据包)
  3.  Leader节点提交
synchronized public void processAck(long sid, long zxid, SocketAddress followerAddr) {
        if ((zxid & 0xffffffffL) == 0) {
            /*
             * We no longer process NEWLEADER ack by this method. However,
             * the learner sends ack back to the leader after it gets UPTODATE
             * so we just ignore the message.
             */
            return;
        }
    
      
        if (lastCommitted >= zxid) {
        
            // The proposal has already been committed
            return;
        }
        Proposal p = outstandingProposals.get(zxid);
        if (p == null) {
            LOG.warn("Trying to commit future proposal: zxid 0x{} from {}",
                    Long.toHexString(zxid), followerAddr);
            return;
        }
        
        p.ackSet.add(sid);
        
        if (self.getQuorumVerifier().containsQuorum(p.ackSet)){             
            if (zxid != lastCommitted+1) {
                LOG.warn("Commiting zxid 0x{} from {} not first!",
                        Long.toHexString(zxid), followerAddr);
                LOG.warn("First is 0x{}", Long.toHexString(lastCommitted + 1));
            }
            outstandingProposals.remove(zxid);
            if (p.request != null) {
                toBeApplied.add(p);
            }

            if (p.request == null) {
                LOG.warn("Going to commmit null request for proposal: {}", p);
            }
            //follower 发送事务ID
            commit(zxid);
           //obser 直接发送数据包
            inform(p);
           //leader 执行commit
            zk.commitProcessor.commit(p.request);
            if(pendingSyncs.containsKey(zxid)){
                for(LearnerSyncRequest r: pendingSyncs.remove(zxid)) {
                    sendSync(r);
                }
            }
        }
    }
 

量大,服务器压力大。需要用到分布式,集群。

三台机器,一个请求如何落到一台机器上?如何协调工作

zookeeper 解决了各服务之间协调工作的内容如下图: 

 

端口 默认2181

1.Leader-follower-observer

2.Leader选取 :?有哪些算法? 

既然是分布式,集群,一个请求只能有一台机器接接收并处理,其他机器如何同步消息?
数据同步怎么办?事务请求走Leader,非事务走所有节点,增删改有Leader节点处理,处理完同步到非Leader;使用了节点zab协议(原子广播协议):数据同步,Leader选取,原子广播。

Zookeeper集群中,当某一个集群节点接收到一个写请求操作时,该节点需要将这个写请求操作发送给其他节点,以使其他节点同步执行这个写请求操作,从而达到各个节点上的数据保持一致,也就是数据一致性。我们通常说Zookeeper保证CAP理论中的CP就只这个意思。何为CAP
Zookeeper集群底层是怎么保证数据一致性的,用的两阶段提交+过半机制来保证的。

事务性请求包括:更新操作、新增操作、删除操作。

非事务性请求:查询操作。 

ZK有哪些节点?

zookeeper:文件类型的树形目录结构 
有序节点:顺序递增
持久化节点:永久存储,存储在磁盘上
临时节点:会话结束即删除节点,不能有子节点,存在冲突:比如 临时节点下在建立了持久节点怎么办,如果在建立个临时节点,生命周期不一样怎么办?
树形结构: 每个节点是 key-vaLue

数据在磁盘中的表示

假设我们现在在Zookeeper中有一个数据节点,节点名为/datanode,内容为125,该节点是持久化节点,所以该节点信息会保存在文件中。

方法一:

方法二:快照+事务日志

当前快照:

 当前事务日志:

 Zookeeper集群中的节点在处理事务性请求时,需要将事务操作同步给其他节点,事务操作是一定要进行持久化的,以便在同步给其他节点时出现异常进行补偿。实际上事务日志还运行数据进行回滚,这个在两阶段提交中也是非常重要的。持久性节点存储在磁盘上每次查询需要IO操作,Zookeeper为了提高数据的查询速度,会在内存中也存储一份数据

 

数据在内存中的表示

Zookeeper中的数据在内存中的表示类似一颗树,必须以/开头,一颗具有父子层级的多叉树,在Zookeeper源码中叫DataTree:

请求处理逻辑

请看下图:

  

请注意,对于上图,Zookeeper真正的底层实现,zk1是Leader,zk2和zk3是Learner,是根据领导者选举选出来的。

非事务性请求直接读取DataTree上的内容,DataTree是在内存中的,所以会非常快。


 
zookeeper 应用:


1.分布式锁:(节点抢占,顺序节点)

  1. 节点抢占 :同级节点是唯一的(同时创建同一个节点,多个应用创建肯定只有一个成功)失败的节点怎么办?watcher:客户端可以监控某一个节点的变化    
  2. 监听方式3中:get exists getchiLdren 设置监控: get /mic true 对mic 节点监控 监控删除事件如 app2可以watcher app1新建的节点事件,如果app1新建的节点有修改会给所有监控对象app2,app3发通知(只触发一次,如果失败则丢掉事件)会发生 惊群问题?会触发所有节点
  3. 顺序节点:创建顺序节点,最小节点获取锁 1 2 3 ;2监控1 3监控2 ,每个节点监控上一个节点

 2.服务注册: 

各个服务通信:rpc协议远程过程服务调用rpc 协议有 hession,dubbo,webservice 框架,服务直接通信用到:序列化/反序列化,反射

 

原文地址:https://www.cnblogs.com/fanBlog/p/9720047.html