• zookeeper


    一,前言

    与redis的联系

    redis 单实例,数据在内存-读取快

    鉴于雪崩击穿等问题 ->复制到集群 HA sentinel 哨兵实现高可用

    不是绝对的实时同步,可能连最终一致性都算不上

    集群模式 分片

    完成分布式 协调分布式锁

    二,zookeeper(不要把zk当做数据库用)

    主从集群 主是单点的(zk运行状态,1.可用状态,有主模型2.不可用状态,无主模型3.不可用状态恢复到可用状态,应该越快越好 200毫秒)

    1.leader可能会挂

    2.导致服务不可用

    3.事实,zk集群及高可用

    4.如果有一种方式可以快速的复制出一个leader

    一个leader多个follower,客户端想连谁就连谁(每个客户端连接会有一个session,即临时节点)

    zookeeper是一个目录结构-->不同目录即为一个节点,可以存数据,官方声明为1M->统一配置管理1.2.3.4.

    持久节点

    临时节点-->session

    序列节点(序列化,要么是持久节点要么是临时节点)

    1.统一配置管理<-1M数据

      分布式锁,临时节点

    client代码实现

     

    2.分组管理<--path结构

            

    锁依托一个父节点,具备 -s

    队列式事务锁

    3.统一命名<--sequential

     

    代表父节点下可以有多把锁

     

    4.同步<--临时节点

    HA 选主

     

     

     

     

     

    担保

    • ZooKeeper非常快速且非常简单。但是,由于其目标是作为构建更复杂的服务(例如同步)的基础,因此它提供了一组保证。这些是:
    • 顺序一致性-来自客户端的更新将按照其发送顺序进行应用。
    • 原子性-更新成功或失败。没有部分结果。
    • 统一视图-无论客户端连接到哪个服务器,客户端都将看到相同的服务视图。
    • 可靠性-应用更新后,此更新将一直持续到客户端覆盖更新为止。
    • 及时性-确保系统的客户视图在特定时间范围内是最新的。

    三 安装启动

    • 1.先安装jdk (下载,解压,配置环境变量)

    export JAVA_HOME=/app/jdk1.8.0_231/

    export CLASSPATH=.:$JAVA_HOME/lib.dt.jar:$JAVA_HOME/lib/tools.jar

    export PATH=$PATH:$JAVA_HOME/bin

    Java-version验证是否安装成功

    • 2.再zookeeper(下载,解压,配置环境变量)

    export JAVA_HOME=/app/jdk1.8.0_231/

    export CLASSPATH=.:$JAVA_HOME/lib.dt.jar:$JAVA_HOME/lib/tools.jar

    export ZOOKEEPER_HOME=/app/zookeeper/apache-zookeeper-3.5.5-bin/

    export PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin

    输入zk按tab键验证是否成功

     

    配置zk相关配置:

    conf/zoo.cfg

    #配置数据文件夹和日志文件夹

    dataDir=/var/houkai/zk

    dataLogDir=/var/houkai/zk/log

    #配置集群  2888: leader接收writer请求用  3888:选主投票用

    server.1=192.168.65.10:2888:3888

    server.2=192.168.65.20:2888:3888

    server.3=192.168.65.30:2888:3888

    server.4=192.168.65.40:2888:3888

    server.5=192.168.65.50:2888:3888

    mkdir -p /var/houkai/zk

    进入/var/houkai/zk文件夹

    vi myid 文件中写自己的id号,即上面的.1.2.3.4.5

    • 3.启动
      • zkServer.sh help 查看帮助
      • zkServer.sh start-foreground
      • java.net.NoRouteToHostException: No route to host (Host unreachable)
      •   service iptables status 查看防火墙状态
      •   service iptables off
      •   service iptables stop 即时生效,重启后复原

    chkconfig iptables off 永久关闭防火墙

    • zkServer.sh status 查看主机状态是主还是从
    • zkCli.sh 启动客户端
      • o ll显示节点
      • o create /newnode "" 创建新的(持久)节点,东西的话不报错但是不创建,所以带个字符串
      • o create -s /newnode  创建(顺序)节点,可以规避节点被覆盖
      • o create -e /newnode   创建(临时)节点
      • o create [-s] [-e] path data acl 其中,-s或-e分别指定节点特性,顺序或临时节点,若不指定,则表示持久节点;acl用来进行权限控制。
      • o create -s -e /newnode
      • o create/newnode/sonnode "koukay" 也可以创建多级节点,数据最大1M,二进制安全的
      • o get /newnode/sonnode 获取节点 因为节点相当于文件夹,所以名字前必须带/
      • o get -s /koukay 获取节点,显示数据参数
      • o set /newnode "hello"为节点设置值
      • o rmr /test 删除节点及数据

     

     

    • 参数解析

    cZxid = 0x0

    ctime = Thu Jan 01 08:00:00 CST 1970

    mZxid = 0x0

    mtime = Thu Jan 01 08:00:00 CST 1970

    pZxid = 0x1469

    cversion = 3

    dataVersion = 0

    aclVersion = 0

    ephemeralOwner = 0x0

    dataLength = 0

    numChildren = 4

    其中:

    cZxid:节点创建时的zxid

    ctime:节点创建时间

    mZxid:节点最近一次更新时的zxid

    mtime:节点最近一次更新的时间

    cversion:子节点数据更新次数

    dataVersion:本节点数据更新次数

    aclVersion:节点ACL(授权信息)的更新次数

    • ephemeral Owner:如果该节点为临时节点,ephemeralOwner值表示与该节点绑定session id.如果该节点不是临时节点,ephemeralOwner值为0

    dataLength:节点数据长度,本例中为hello world的长度

    numChildren:子节点个数

    netstat -napt |egrep '(2888|3888)'

     

    四,paxos,ZAB(zk原子广播),watch,API -->zk client,callback-->reactive 编程 更充分的压榨os,hw资源,性能

    • zookeeper分布式协调扩展,可靠性,时序性,扩展性
    • 扩展性
      • o 框架架构-->角色

    leader  

    主节点

    follower

    从节点

    observer

    Observer与follower类似但不参与投票,只是简单的接收投票结果,因此我们增加再多的Observer,也不会影响集群的写性能

     

    • 读写分离 observer放大查询能力
      • 只有follower才能选举
      • zoo.cfg

    server.1=192.168.65.10:2888:3888

    server.2=192.168.65.20:2888:3888

    server.3=192.168.65.30:2888:3888

    server.4=192.168.65.40:2888:3888

    server.5=192.168.65.50:2888:3888:observer

    • 可靠性
      • o 攘其外必先安其内(有主有从)
      • o 快速恢复leader
      • o 数据可靠,可用一致性
        • 攘其外  一致性?(先同步再提供服务)  最终一致性  过程中节点是否对外提供服务(zk挂了,停止服务,进行选举)
        • 分布式

    https://www.douban.com/note/208430424/  (关于分布式的文章,更偏向于paxos)

    Z(ZK)A(原子)B(广播) 作用在可用状态 有leader时

    • 分布式流程
      • 概念解释:
        • 原子:只有成功或失败,没有中间状态 (队列+2pc)
        • 广播:分布式多节点,全部收到消息(过半)
        • 队列:FIFO 顺序性
        • zk的数据状态在内存用磁盘保存日志
        • 一个leader两个follower ,每个follower和leader之间有个队列
          •  

    client

     

    follower

     

    queue

    leader

    queue

     

    follower

     

    client

    客户端

    1客户端请求创建节点,请求到达follower

    从节点

    4-1-log队列将日志送达从节点

    2从节点在主节点创建

    3Zxid事务id

    从节点在主节点创建

    4-1-log队列将日志送达从节点

    从节点

    1客户端请求创建节点,请求到达follower

    客户端

     

    从节点返回创建状态OK

    sync可选项

    4-1-ok

    从节点收到日志后返回OK到队列

    主节点返回OK日志

    4-1-ok

    主节点返回OK日志

    4-1-ok

    从节点收到日志后返回OK到队列

    sync可选项

    从节点返回创建状态OK

     

    • 集群状态下如何选举leader
      • 两个场景
        • 场景一,第一次启动集群
        • 场景二,leader挂了后重启集群
        • 自己会有myid和Zxid 选举标准
          • 经验最丰富的的Zxid
          • Zxid相同就找比较大的myid
          • *,过半通过的数据才是真数据,你见到的可用的Zid ,4台机器,3台通过
          • 选举过程
            • 3888造成两两通信
            • 只要任何人投票,都会触发那个准leader发起自己的投票
            • 推选制,先比较zxid,如果zxid相同,再比较myid

     

    • watch(监控,观察)
      • o 统一目录结构
      • o 客户端1
      • o 客户端2
      • o 客户端1&客户端2
        • 客户端在统一目录结构创建节点,删除修改节点会有相应的事件,事件会触发回调函数将事件信息返回给另一个客户端
        • 客户端1与服务端连接在统一视图目录树结构中创建一个临时节点(node:  /oozz/a),建立连接,有一个session和ephemeralOwner(如果不是临时节点,该值为sessionid,如果是临时节点该值为1)
        • 客户端2可以通过get /ooxx/a获取该节点,也可以通过watch /ooxx/a监控该节点
        • 两个客户端之间也有通信,可以开启一个线程检测心跳

     

    • API demo

    packagecom.koukay.zookeeper;

     

    importorg.apache.zookeeper.*;

    importorg.apache.zookeeper.data.Stat;

     

    importjava.io.IOException;

    importjava.util.concurrent.CountDownLatch;

     

    publicclassApp{

    publicstaticvoidmain(String[]args)throwsException{

    System.out.println("HelloWorld");

     

    //zk是有session概念的,没有连接池的概念的

    //watch观察回调分为两类

    //watch的注册只发生在读类型调用,get,exist

    //第一类,newzk的时候,传入的watch,这个watchsession级别的,pathnode没有关系

    CountDownLatchcd=newCountDownLatch(1);

    ZooKeeperzk=newZooKeeper("192.168.65.10:2181,192.168.65.20:2181,192.168.65.30:2181,192.168.65.40:2181,192.168.65.50:2181"

    ,3000,

    newWatcher(){

    /**

    *watch的回调方法

    *@paramevent

    */

    @Override

    publicvoidprocess(WatchedEventevent){

    Event.KeeperStatestate=event.getState();

    Event.EventTypetype=event.getType();

    Stringpath=event.getPath();

    System.out.println("==========newzkwatch"+event.toString());

    switch(state){

    caseUnknown:

    break;

    caseDisconnected:

    break;

    caseNoSyncConnected:

    break;

    caseSyncConnected:

    System.out.println("==================>connected");

    cd.countDown();

    break;

    caseAuthFailed:

    break;

    caseConnectedReadOnly:

    break;

    caseSaslAuthenticated:

    break;

    caseExpired:

    break;

    caseClosed:

    break;

    }

    switch(type){

    caseNone:

    break;

    caseNodeCreated:

    break;

    caseNodeDeleted:

    break;

    caseNodeDataChanged:

    break;

    caseNodeChildrenChanged:

    break;

    caseDataWatchRemoved:

    break;

    caseChildWatchRemoved:

    break;

    }

    }

    });

    cd.await();

    ZooKeeper.Statesstate=zk.getState();

    switch(state){

    caseCONNECTING:

    System.out.println("===========ing======================");

    break;

    caseASSOCIATING:

    break;

    caseCONNECTED:

    System.out.println("===========ed======================");

    break;

    caseCONNECTEDREADONLY:

    break;

    caseCLOSED:

    break;

    caseAUTH_FAILED:

    break;

    caseNOT_CONNECTED:

    break;

    }

    StringpathName=zk.create("/ooxx","olddata".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);

    Statstat=newStat();

    byte[]node=zk.getData("/ooxx",newWatcher(){

    @Override

    publicvoidprocess(WatchedEventevent){

    System.out.println("===========getDataWatch"+event.toString());

    try{

    //trueDefaultWatch被重新注册(newzk的那个watch)

    zk.getData("/ooxx",true,stat);

    }catch(KeeperExceptione){

    e.printStackTrace();

    }catch(InterruptedExceptione){

    e.printStackTrace();

    }

    }

    },stat);

    System.out.println("=================="+newString(node));

    //触发回调

    Statstat1=zk.setData("/ooxx","newData".getBytes(),0);

    //第二次还会触发吗

    Statstat2=zk.setData("/ooxx","newData01".getBytes(),stat1.getVersion());

    System.out.println("----------------asyncstart--------------");

    zk.getData("/ooxx",false,newAsyncCallback.DataCallback(){

     

    @Override

    publicvoidprocessResult(intrc,Stringpath,Objectctx,byte[]data,Statstat){

    System.out.println("----------------asyncover--------------");

    System.out.println("----------"+ctx.toString());

    System.out.println("----------"+newString(data));

    }

    },"123");

    System.out.println("----------------asynccallback--------------");

    Thread.sleep(2222222);

     

    }

    }

    五,zookeeper分布式协调 配置 分布式锁

    分布式配置

    zookeeper配置数据data

    客户端

    get()

    watch()

    修改设置配置

    触发回调

    分布式锁

    1,争抢锁,只有一个人能获得锁

    2,获得锁的人出问题,临时节点(session)。

    3,获得锁的人成功了。释放锁。

    4,锁被释放、删除,别人怎么知道的?

    4-1:主动轮询,心跳。。。弊端:延迟,压力

    4-2:watch:  解决延迟问题。。  弊端:压力

    4-3:sequence+watch:watch谁?watch前一个,最小的获得锁~!一旦,最小的释放了锁,成本:zk只给第二个发事件回调!!!!

  • 相关阅读:
    java 类加载与初始化
    字符串匹配
    二分查找
    一般css样式开头公共部分
    js或jquery实现图片轮播
    w3chtml页面和css书写规范
    前端学习网站
    相关学习网站
    char对比varchar
    用抽象类或者接口?
  • 原文地址:https://www.cnblogs.com/hikoukay/p/12112905.html
Copyright © 2020-2023  润新知