zookeeper

应用场景

  • 统一命名服务:在分布式环境下,需要对应用/服务进行统一命名,便于识别(Ip是记不住的)
  • 统一配置管理:分布式环境下,配置文件同步
  • 统一集群管理:掌握每个节点的状态
  • 服务器节点动态上下线
  • 软负载均衡

安装

集群配置

启动多个zookeeper-server,选择leader时,必须要大于一半以上,所有最好是奇数个节点。

接下来每个节点都需要操作

步骤一:zoo.cfg

tickTime=2000
dataDir=/var/lib/zookeeper/
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888	#2888节点通信用的端口,3888选举lead时用的端口
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888

步骤二:

通过为服务器创建一个名为myid的文件,将服务器ID分配给每台计算机,该文件位于配置文件参数dataDir所指定的该服务器的数据目录中。


基础

  1. 架构
  2. 层次命名空间
  3. 会话
  4. 监视

架构

ZooKeeper的架构

层次命名空间

  • zookeeper文件系统在内存中的形式是树状结构。

  • Zookeeper节点称为znode

  • zookeeper的根目录是\

znode 构成

  • stat:此为状态信息,描述该Znode版本、权限信息
    • 版本号:每当znode相关联的数据改变,版本会递增
    • ACL:权限管理
    • 时间戳:创建和修改Znode所经过的时间,
  • data:Znode关联的数据,只有1M的空间
  • children[]:指向Znode子节点的指针

znode类型

  • 持久节点:A客户端创建的znode节点,A断开连接,znode节点依旧存在
  • 临时节点:A客户端创建的节点,A断开连接,znode节点自动删除
  • 顺序节点:可以是临时的也可以是持久的。当一个新的znode被创建为一个顺序节点,zookeeper通过将10位序列号附加在原名称来设置znode的路径。例如 mynode,系统添加znode节点时生成的是mynode00000000001

会话

会话的请求按FIFO顺序执行。每个客户端会分配一个会话ID。

客户端定时发送心跳请求,服务端在指定时间未接受到心跳包,默认客户端宕机,促使断开连接,临时节点删除

监视

发布订阅。客户端给特定znode(相当于redis的key)添加watches。当znode更改时,watches给订阅的客户端推送消息。

集群工作流程

客户端数据写入znode

C端连接集群A节点(所有节点都可以),A节点转发给leader节点,leader将向有所的跟随者发送写入请求。大部分节点返回成功则向C端返回成功。

客户端向znode读取数据

因为集群数据时同步,哪个一个zookeeper节点上的数据都一致。

集群节点数

  • 单个节点,可以使用,但是单点故障无法容灾
  • 偶数节点,平均无法选择出多数的一方,不建议使用
  • 奇数节点,有一方是多出一个节点的,建议使用

leader选举

leader选举是保证 分布式数据一致性。

节点状态

  • looking:寻找leader,处于该状态需要进入选举流程
  • leading:领导者状态,处于该状态节点已经成为领导者
  • following:跟随者状态
  • observer:观察者状态,

事务id

zookeeper状态的每次变化都会接收一个ZXID(zk 事务id)形式的标记。64位 递增 的 唯一值

注册中心

以swoole web服务为例

  1. web服务集群,会有多台主机,并且启动多个swoole http服务
  2. swoole启动http服务时,fock一个子进程通过zookeepctl进行连接zookeeper服务,并在/swoole_web目录下创建一个以ip命名的临时znode节点。
  3. 再在每台机器上起一个脚本,连接zookeeper充当另外一个客户端,监视(watches) /swoole_web目录,并把此目录下的znode节点的ip保存到一个文件或redis内存中,这样就可以实时上下线服务
  4. 当swoole服务宕机,zookeeper客户端进程也会挂掉,zookeeper服务端发现此客户端没有发送心跳包,则会删除此客户端的临时znode节点。

分布式锁

  1. 每个客户端想要抢占锁,都建立一个znode临时节点。通过有序临时节点,形成一个有序队列(为什么要临时的,因为当客户端宕机后不会产生死锁)
  2. 判断有序临时节点的排序
    • 如果是第一位,说明前面没有其他客户端抢占锁,此客户端直接获取锁,执行业务逻辑
    • 如果是非第一位,说明前面有客户端抢占着锁,此时客户端给前一个临时有序节点加一个监视(watch),当前一个临时有序节点被删除后,则此客户端抢占锁,执行业务逻辑
  3. 客户端执行完业务逻辑,直接断开连接,则删除临时节点,让出锁
#创建客户端
$client = \Zookeeper(socket);

#创建lock根节点
$lock_root = 'lock_root';
$client->create($lock_root, 'value', $acl);

#创建临时有序节点
$znode_lock = 'test_lock';
$client_znode_name = $client->create($znode_lock, 'value', $acl, Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE);

#获取此目录下的所有临时有序节点
$list = $client->getChildren($lock_root);
sort($list);	//数组对象必成数组

#判断是否是第一个节点
if(current($list) == $client_znode_name){
    #todo 
    echo "获取锁成功,可以执行业务逻辑";
} else {
    #不是第一个节点,获取此节点的前一个节点
    $index = array_search($client_znode_name, $list);
    $before = $list[$index-1];
    
    #给前一个节点加watch
    $is_locked = true;
    $client->get($before, function() use (&$is_locked){
        #watch回调,将被锁着的状态改成未锁
        $is_locked = false;
    });
    
    # 如果未解锁,则阻塞等待watch返回
    while($is_locked){
        usleep(500000);	
    }
}

#经过上面的步骤,client获取到锁,执行业务逻辑
//todo

# 解锁
$client->delete($client_znode_name);
$client->close();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值