design\project\学习 ZooKeeper 读书笔记

ZooKeeper

文章目录

  • ZooKeeper
    • 对强一致性的理解
            • 顺序一致性 Order
            • 及时性
            • 读已提交 RC
            • 单系统快照(可重复读 RR)
    • ZooKeeper 概述
        • ZooKeeper 的强一致性
        • 设计目标
            • 简单:
            • 可靠:
            • 强一致性:
            • 高效:
        • 节点数据模型
        • 瞬时节点
        • 顺序节点
        • watches 监听器
        • API
        • 架构
        • 集群配置
        • 使用场景

分布式的,高性能的协调服务

对强一致性的理解

参考链接:MIT 6.824: Distributed Systems —— Lecture 8: Zookeeper

Linearizeability 可串行的(强一致性)要求

  • 操作存在一个全局唯一的 Order

  • 实时(Matches real time)

  • 读已提交 RC,RR(reads see preceding write in the order)

顺序一致性 Order

只要最终 w 的值的变化存在全局唯一的顺序。则认为符合顺序一致性

design\project\学习 ZooKeeper 读书笔记_第1张图片

及时性

在一定的时间内及时同步完成,或者 zookeeper 可以通过调用 sync 强制同步

design\project\学习 ZooKeeper 读书笔记_第2张图片

读已提交 RC

zookeeper 可以通过调用 sync 强制同步

design\project\学习 ZooKeeper 读书笔记_第3张图片

单系统快照(可重复读 RR)

服务端过滤重复的请求,这个 zookeeper 好像也通过 zxid 解决了,好像

design\project\学习 ZooKeeper 读书笔记_第4张图片

有没有这样一个系统,帮助我们解决这些问题呢? 有!!!ZooKeeper

ZooKeeper 概述

协调服务很难做好。他们特别容易出错,比如竞争死锁

zookeeper :分布式应用的,服务协调器,提供同步(synchronization)、配置(configuration)以及组和服务发现(naming)功能

ZooKeeper 的强一致性

  • 保证串行写入(写入强一致性),客户端收到更新成功前,数据已经同步到所有副本

  • 保证客户端 FIFO 顺序(参考上文:顺序一致性)

设计目标

简单:
  • 分层的命名空间(znodes,类似文件和目录)

    • 数据保存在内存中,高吞吐量和低延迟

    • 高性能、高可用,可用于大型分布式系统

    • 严格的有序性意味着可以实现复杂的同步

可靠:
  • ZooKeeper 可以有自己的副本集

  • 事务日志和快照都放在持久化存储中

  • 客户端维护一个 TCP 连接,发送心跳、请求、获得响应、支持事件

强一致性:
  • ZooKeeper 在每个操作都带一个递增的数字 zxid
高效:
  • ZooKeeper 读写性能很快,尤其是读,适合当读写比 10:1 的时候

design\project\学习 ZooKeeper 读书笔记_第5张图片

*官网扣的图,如有侵权请联系作者删除*

节点数据模型

  • 像 linux 文件系统一样,允许即是文件也是目录
class DataNode {
    // 每个节点有自己的数据
    byte[] data;
    // acl 访问控制列表,不继承父节点权限(用于限制谁可以做什么)
    Long acl;
    // 含版本号、访问控制列表变化、时间戳
    public StatPersisted stat;
}
class DataTree {
    DataTree(DigestCalculator digestCalculator) {
        nodes.put("", root);
        ...
        // 节点有自己的子节点
        /** add the proc node and quota node */
        root.addChild(procChildZookeeper);
        nodes.put(procZookeeper, procDataNode);

        procDataNode.addChild(quotaChildZookeeper);
        nodes.put(quotaZookeeper, quotaDataNode);

        addConfigNode();
    }
}
class StatPersisted {
    // 事务id,ZooKeeper 状态的每次更改都会收到一个 Zxid(所有变化的总排序)
    // 为了避免时钟同步,zookeeper 不适用实时时间,可以将实时时间加在 znode 上
    // 高32位是 epoch,标识 leader 关系;低32位用于递增计数
    // leader 崩溃恢复后,follower 只听从当前 epoch 的 leader
    // 创建 zxid
    private long czxid;
    // 修改 zxid
    private long mzxid;
    // 谁最后一次修改子节点
    private long pzxid;
    // znode 创建时间戳
    private long ctime;
    // 修改时间
    private long mtime;
    // 数据版本,对一个节点的每次更改都会增加一个版本号
    private int dataVersion;
    // 子节点版本
    private int cversion;
    // acl 版本号
    private int aversion;
    // 临时节点拥有者 sessionId
    private int ephemeralOwner;
    // 数据长度
    private long dataLength;
    // 子节点长度
    private int numChildren;
}
  • ZooKeeper 被设计用于存储协调数据:(状态信息、配置、Naming)所以每个节点的数据通常很小(1~1000 byte)

    • 如果想要存数据,可以存指针,地址,数据库 ID 号
  • 每当 znode 的数据发生变化时,版本号就会增加

瞬时节点

  • 当会话结束时,znode 被删除,删除有一定的延迟

  • 临时节点不可以有子节点

顺序节点

  • 通过 -s 指定创建顺序节点,顺序节点名称之后会带 10 位的自增数字,栗如 test0000000001

  • 可以和临时节点结合起来用

watches 监听器

客户端收到更新成功前,数据已经同步到所有副本,所以结果通过 watches 来异步接收通知呗

  • 客户端可以在 znode 上设置 watches (监听必须绑定在 zNode 上)

  • 当 znode 变化时,watches将被触发并移除

  • 连接中断,客户端将收到一个本地通知

  • 3.6.0 中的新功能: 客户端还可以在一个 znode 上设置永久的、递归的监视器

API

class ZooKeeper {
    public String create();
    public void delete();
    public Stat exists();
    public byte[] getData();
    public Stat setData();
    public List<String> getChildren();
    // Asynchronous sync. Flushes channel between process and leader
    // 客户端想得到最新的数据,就发送一个 sync,将当前指令压栈等待同步后执行
    // 异步的实现当前进程与 leader 之间的指定 path 的数据同步
    public void sync();
}

架构

  • 来自客户机的所有写请求都被转发到一个称为 leader 的服务器。其余的 ZooKeeper 服务器被称为 follower,接收来自 leader 的消息建议并传递消息

  • 消息传递层负责在 leader 宕机后重新选举,并同步 follower 和 leader

  • ZooKeeper 使用自定义的原子消息传递协议(ZAB 协议)

  • ZooKeeper 的集群式通过 log 的方式同步???

集群配置

  • 配置文件

    initLimit = 连接到 leader 的时限
    syncLimint = follower 与 leader 之间请求和应答时限
    
    # server.x 与 data 目录中 myid 文件对应
    # 第一个端口用于通讯,第二个端口用于选举
    server.1=127.0.0.1:2991:3991
    server.2=127.0.0.1:2992:3992
    server.3=127.0.0.1:2993:3993
    
  • 集群角色

    • leader

    • learner

      • follower:接手客户端请求、返回结果,可以参与选主过程投票

      • observer:观察者,不参与选主投票

  • 更新模式

    • 写请求 Forwarder 到 Leader,ZAB 协议广播,收到一半以上写成功的应答,持久化,报告客户端写成功了

    • WAL(Write-Ahead-Log),所有更新先写 WAL,然后对内存中数据更新,最后 ACK;(感觉 WAL 模式能用来做手动业务回滚啊)

    • 定期 Snapshot

    • ZAB 协议:原子广播协议

      • 选主模式

      • 广播模式

使用场景

  • 服务发现

  • 配置中心

  • 负载均衡(临时节点+slot 算法)

  • 分布式通知与协调(通过zk 提供的 listener 机制实现串行,并行分布式通知。实现简单的调度(调度应用负责发布任务,工作应用负责执行))

  • 集群服务监控(临时节点)

  • 分布式锁(服务协调,独占锁(争创临时节点,抢不到 watch 开抢),时序锁)

  • 分布式队列(详见:百度)

你可能感兴趣的:(java,zookeeper,学习,分布式)