大数据之zookeeper(一) --- zookeeper介绍,zk安装(单机版),api,zknode,Sessions,Watcher,工作流程分析

一、zookeeper
-------------------------------------------------
    1.管理大量主机的协同服务

    2.是一个分布式应用,实现了分布式读写技术

    3.提供的服务有:
        名称服务    //按名称区分集群中的节点
        配置管理,   //对加入的节点进行最优化的处理
        集群管理,   //实时感知集群中节点的增减
        领导推选服务, //leader和follower推选机制
        锁与同步        //修改时锁定数据,实现容灾
        高可靠数据注册机制   //节点宕机,数据仍然可用


二、ZK安装(单机版)
----------------------------------------------------------
    1.下载zookeeper-3.4.9.tar.gz

    2.tar开

    3.创建符号连接
        ln -s zookeeper-3.4.9  zk

    4.配置环境变量
        ZK_HOME="/soft/zk"
        path=".....:/soft/zk/bin"

    5.source一下

    6.配置zk
        a.[zk/conf/zoo.cfg]
            $> cp zoo_sample.cfg zoo.cfg

            -- 修改快照路径
            # the directory where the snapshot is stored.
            # do not use /tmp for storage, /tmp here is just
            # example sakes.
            dataDir=/home/ubuntu/zookeeper

    7.启动zk服务
        $>cd /soft/zk/bin
        $>zkServer.sh start

    8.查看端口,验证是否启动
        $> netstat -ano | grep 2181

    9.启动客户端,连接到服务器
        $> zkCli.sh -server s100:2181

    10.进入zk命令行,查看帮助
        $[zk: s100:2181(CONNECTED) 1]  help


三、使用zk
-----------------------------------------
    1.创建节点以及节点关联的数据
        [zk> create /a  tom         //在根节点下创建路径 /a  关联的数据是tom。
                                    //而且不能跨节点创建,也就是父节点必须存在
                                    //不关联数据也是不行的
    2.查询节点
        [zk> get /a                 //查看/a 节点关联的数据信息

    3.更新节点数据
        [zk> set /a tomse           //更新节点关联的数据,并且版本+1

    4.删除节点
        [zk> delete /a              //不能删除非空节点
        [zk> rmr /a                 //递归删除,可以删除非空节点


四、通过API访问zk
-----------------------------------------------------
    1.建立java项目,并添加maven依赖
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

public class TsZK {

    public ZooKeeper zk = null;

    @Before
    public void getZk() throws Exception {
        //连接串,可以是多个ip和端口组成的串
        String conStr = "192.168.43.131:2181";
        zk = new ZooKeeper(conStr, 5000, null);
    }

    /**
     * 测试递归查询:列出所有节点
     */
    @Test
    public void tsLSR() throws Exception {
        tsLS("/");
    }


    public void tsLS(String root) throws Exception {

        //查询节点
        List<String> list = zk.getChildren(root, null);
        if (list !=null && list.size() > 0) {
            for(String s : list)
            {
                if(root == "/")     //说明是根
                {
                    System.out.println(root  +s);
                    tsLS(root +s);
                }
                else
                {
                    System.out.println(root + "/" +s);
                    tsLS(root + "/" +s);
                }
            }
        }
    }


    /**
     * 测试创建节点
     */
    @Test
    public void tsCreateNode() throws Exception {
        zk.create("/mynode", "mycreatenode".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        tsLSR();
    }

    /**
     * 删除节点
     */
    @Test
    public void tsDelNode() throws Exception {
        zk.delete("/mynode",0);
        tsLSR();
    }

    /**
     * 判断路径是否存在
     */
    @Test
    public void tsExists() throws Exception
    {
        Stat stat = zk.exists("/a/b", true);
        if (stat == null) {
            System.out.println("path not exits");
        }
        else
        {
            System.out.println("path exits" + stat.getNumChildren());
        }
    }

    /**
     * 查看节点数据
     */
    @Test
    public void tsGetNodeData() throws Exception
    {
        Watcher w = new Watcher() {
            public void process(WatchedEvent event) {
                System.out.println("data is changed");
            }
        };
        byte [] bs = zk.getData("/a",w,null );
        System.out.println(new String(bs));
    }

    /**
     * 设定节点数据
     */
    @Test
    public void teSetNodeDate() throws Exception{
        Stat stat = zk.exists("/a", true);
        zk.setData("/a", "hao".getBytes(), stat.getVersion());
    }

    /**
     * 测试监听机制
     * 反复使用同一个观察者,实现反复监听
     * 回调函数中添加注册机制,实现反复监听
     */
    @Test
    public void tsWatch() throws Exception {
        final Stat stat = zk.exists("/a", true);

        //反复使用同一个观察者,实现反复观察
        Watcher w = new Watcher() {

            public void process(WatchedEvent event) {
                System.out.println("data id changed");
                try {
                    zk.getData("/a", this, null);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        byte[] bs = zk.getData("/a", w, stat);

        System.out.println(new String(bs));
        while(true)
        {

        }
    }

    /**
     * 测试监听机制
     * 递归实现持续监听
     */
    @Test
    public void ts()
    {
        tsWatch_always();
        while (true) {
        }
    }

    public void tsWatch_always()
    {
        try{
            final Stat stat = zk.exists("/a", true);
            byte[] bs = zk.getData("/a", new Watcher() {
                public void process(WatchedEvent event) {
                    System.out.println("data id changed");
                    tsWatch_always();
                }
            }, stat);
            System.out.println("data = " + new String(bs));
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 测试zk读
     */
    public void tsRead()
    {

    }
}



五、ZK架构
-----------------------------------------------------
    1.Client:
        从server获取信息,并一定间隔向服务器发送心跳,证明alive.
        连接服务器时,服务器会回传一个确认信息,如果没有得到响应,客户端就会尝试连接zk集群里的另外一台服务器

    2.Server:
        zk集群中的一员,向客户端提供所有服务,向客户端发送ack信息,表示自己alive

    3.ensemble:
        一组服务器,最小的节点数是3

    4.leader:
        服务器的一个节点,如果节点故障,自动恢复一个节点作为leader.
        服务器启动的时候,会推选一个节点作为leader

    5.follower:
        作为leader的推选,而被推选为leader


六、ZNode
---------------------------------------------------------
    1.znode是zk服务器中的节点(路径,kv对),由版本号,时间戳,访问控制列表,数据长度等组成
        a.版本:数据变化版本递增,多客户端执行并发时尤其重要。

        b.Acl:访问控制列表,权限控制,掌控所有节点的读写操作。类似于Linux的GUO

        c.时间戳:毫秒数,从数据创建或者被修改至今的毫秒数值

        d.DataLength:数据的字节数量,最大为1M

    2.节点类型
        a.Persistence znode 持久性节点
            -- client退出也存在,默认节点选项

        b.Ephemeral znode 临时性节点
            -- client断开连接即删除,仅在客户端活跃时有效。
            -- 不能有子节点。
            -- leader推选的时候扮演重要角色

        c.Sequential znode 序列性节点
            -- 既可以是持久节点,也可以是临时节点。特点就是在你自定义的名字后面加上10个数字
            -- 即使你创建相同名称的节点,也会不同。因为后面的10位数字是递增的
            -- 在同步的时候很重要


七、Sessions 会话
-----------------------------------------------------------
    1.FIFO:先进先出
    2.一旦Client连接到Server,Session就建立了。
    3.Client固定间隔向server发送心跳,以确定会话是有效的.超时的话,就认为客户端挂掉了
    4.Cilent一旦被认为挂掉,就会删除临时节点


八、Watch 监视者
------------------------------------------------------------
    1.被观察的节点上的数据一旦发生改变,就会通知观察者
    2.客户端可以在read节点[zk.getData()]的时候,注册观察者。
    3.观察模式只触发一次。
    4.如果会话过期或者关闭,观察者也会被删除


九、zk工作流程
---------------------------------------------------------------
    1.zk集群启动后,client会连接到集群中的其中的一个节点,这个节点可以是leader,也可以是follower

    2.连通后,node会分配一个id给连接的client作为其标识。并发送ack身份确认信息给client

    3.如果客户端没有收到ack,说明尝试连接的服务器有问题。那么客户端就会查找集群中的其他节点,继续请求连接,直到收到ack

    4.client一旦连接成功,就会周期性的向server发送心跳信息,保证连接不会丢失

    5.client读取数据:
        client读取数据,发送读请求给连接的zknode,zknode读取自己的数据库,返回节点数据给client

    6.client写入数据:
        client存储数据,发送要写入的路径和数据(k,v)给连接的zknode,zknode会将kv数据转发给leader。
        leader在补发给所有的follower。只有当大多数(超过半数)的节点响应成功,写操作才会成功。







猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/82659777