栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

细读经典第一期——从Paxos到Zookeeper 分布式一致性原理与实践(4)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

细读经典第一期——从Paxos到Zookeeper 分布式一致性原理与实践(4)

目录

七、Zookeeper技术内幕

7.1系统模型

7.1.1数据模型

7.1.2 节点类型

7.1.3 Znode的版本信息——保证分布式数据操作的原子性

7.1.4 Watcher——数据变更通知

7.1.5 ACL访问控制

7.2序列化协议

7.3 客户端

7.4 会话

7.4.1 会话状态转换

7.4.2 会话创建


七、Zookeeper技术内幕

ZK最重要的一点就是利用自己的数据模型实现分布式系统的一致性

7.1系统模型

7.1.1数据模型

Znode数据节点是最小单元,由Znode构成了树。

对于每一个事务请求,Zookeeper都会为其分配一个全局的事务ID,用ZXID来表示,每个ZXID对应一次更新操作,ZXID用来保证全局顺序操作

7.1.2 节点类型

持久节点(PERSISITENT),临时节点(EPHEMERAL)和顺序节点(SEQUENTIAL),具体创建过程中,会形成

持久节点,持久顺序节点,临时节点,临时顺序节点四类,其中临时节点只能作为叶子节点,且与会话绑定,而非TCP连接

7.1.3 Znode的版本信息——保证分布式数据操作的原子性

Znode的版本信息用来保证分布式数据的原子性操作,每个数据节点有三个版本信息

version表示当前节点自从创建之后被更新的次数,即使数据一样,只要版本发生变化,version就会改变,例如当一个Znode被创建后,其version为0,同样,这样的改变也会存在所谓ABA问题,所以这里的版本并不是指Znode的本身的内容是否变化,而是是否有用户对节点内容进行变更。

乐观锁控制事务分成如下三个阶段:数据读取,写入校验,和数据写入

Znode在进行setDataRequest时会进行版本比较,客户端可以使用CAS,也可以不使用CAS,如果使用但版本不一致,会抛出BadVersionException异常

7.1.4 Watcher——数据变更通知

客户端向服务端注册Watcher监听,当服务端一些指定的事件触发了Watcher,那么就会向指定客户端发送一个事件通知来实现分布式通知功能

 Client向zookeeper注册Watcher时,会将Watcher信息存储在WatchManager中,当服务端出发Watcher事件之后,会向客户端发送通知,客户端线程从WatchManager中取出Watcher执行相应的回调逻辑。

Watcher接口内定义了两个枚举:KeeperState和EventType和一个方法process(WatchedEvent event)

本质上,还是在服务端维护了一个Map>,将节点路径和该节点路径的Set集合进行映射。

总结Watcher特性:

一次性:一旦一个Watcher被触发,就会从Set中移除该Watcher,因此在使用Watcher时,要确定是否需要在Watcher触发后再次注册Watcher。
轻量:WatchedEvent是整个Zookeeper做Watcher的最小通知单元,且只包含三个成员变量,也就是说process回调只会告诉客户端发生了事件,而不会说明事件的具体内容,对于变更前后的数据都需要客户端自己去获取。从而做到轻量级的通知机制。

7.1.5 ACL访问控制

UGO(user,group,others)转为ACL(Scheme:id:permission)

7.2序列化协议

Zk采用jute序列化组件

7.3 客户端

核心部件:

Zookeeper实例:ClientWatcherManager客户端WatcherManager

HostProvider:服务器地址管理器

ClientCnxn:客户端核心线程,其中又包含SendThread(用于建立TCP通信)和EventThread(事件处理线程),ZK客户端创建一次会话的过程:

7.4 会话

7.4.1 会话状态转换

 图片来源:[ZooKeeper]ZooKeeper的会话状态_zjysource的专栏-CSDN博客_zookeeper会话状态

会话状态CONNECTING,CONNECTED,RECONNECTING,RECONNECTED,CLOSE。

7.4.2 会话创建

(1)Session客户端会话实体

    interface Session {
        // 用sessionId唯一标识一个会话
        long getSessionId();
        // 超时时间
        int getTimeout();
        // 是否已经关闭
        boolean isClosing();
    }

sessionId生成规则,左移24位是为了把二进制日期前的0都移除,之后无符号右移8位,把高8位给id腾出位置,之后把id按位与在64位时间的高8位,最终得一个根据时间唯一确定的sessionId。(每次一有时间生成id我就想到时钟回拨。。)

    public static long initializeNextSessionId(long id) {
        long nextSid;
        nextSid = (Time.currentElapsedTime() << 24) >>> 8;
        nextSid = nextSid | (id << 56);
        if (nextSid == EphemeralType.CONTAINER_EPHEMERAL_OWNER) {
            ++nextSid;  // this is an unlikely edge case, but check it just in case
        }
        return nextSid;
    }

 最后,为了管理session,ZK提供了SessionTracker接口进行管理。

// sessionId和session的映射
protected final ConcurrentHashMap sessionsById = new ConcurrentHashMap();
// session和session超时时间的映射
protected final ConcurrentMap sessionsWithTimeout;

7.4.3 会话管理

ZK的会话管理主要是由SessionTracker负责,采用“分桶策略”,

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/337900.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号