0%

zookeeper介绍

为什么需要zookeeper

对于多线程的弊端,看下图

由于多线程的运行比较难,所以把线程换成进程,相当于每台服务器上跑一个程序,相同的程序运行在多个服务器集群上,是为了解决单台服务器面对高并发处理不过来的情况
但是对于集群又会出现一些新的问题

  • 多台服务器一个集群,如何保证所有机器共享的配置信息一致
  • 有一台服务器挂掉了,其他机器如何感知
  • 用户量突然暴增,需要新增机器缓解压力,如何做到不重启集群完成机器的添加
  • 分布式系统,怎么高效协同多台服务对同一网络文件进行写操作
    因此需要一个能让各个程序进行协同的工具 zookeeper应运而生

zookeeper介绍

zookeeper是一个分布式服务协调组件,特点是数据存于内存中的,持久化实现在日志中。它的内存类似于树形结构,且高吞吐低延迟。
组成zookeeper服务的服务器必须彼此了解,它们维护内存中的状态图像,以及持久化存储中的事务日志和快照。
客户端连接到单个zookeeper服务器,客户端维护TCP连接,通过该连接发送请求,获取响应,获取监听事件以及发送tick。如果服务器的TCP连接中断,则客户端将连接到其他服务器。

zookeeper可以做什么

  • 主要用于分布式系统,可以用zookeeper做统一配置管理、统一命名服务、分布式锁、集群管理。
  • 使用分布式系统对节点管理

zookeeper数据结构

与Unix文件系统类似,可以看做是一棵树,以”/“为根节点,每个节点叫做ZNode,每个节点可以通过路径来标识
zookeeper的节点称为Znode

znode类型

  • 短暂/临时(Ephemeral)节点:当客户端和服务器断开连接后,所创建的Znode会自动删除(临时节点不能挂子节点,只有永久节点才可以)
  • 持久(Persistent)节点:当客户端和服务器断开连接后,所创建的Znode不会删除
  • 无序(Non-sequence)节点:多个客户端同时创建同一个无序节点时,只有一个可以创建成功,其他均失败,且节点名字与指定名完全相同
  • 有序(Sequence)节点:创建出的节点名在指定名称之后带有10位10进制的序号,多个客户端创建同一名称节点时,都能成功,只是序号不同
    Znode包含ACL权限控制、修改/访问时间、最后一次操作的事务id(zxid)等

zookeeper的特点

  • 原子性 只有成功或失败,没有部分结果
  • 有序(顺序一致性)
    zookeeper给每个更新贴上一个数字,这个数字反映了所有zookeeper事务的顺序
    • Zxid:zookeeper中每次写请求都对应一个唯一的事务id,称为Zxid,它是全局有序的,如果Zxid1小于Zxid2,那么Zxid1一定会发生在Zxid2前
    • version numbers:版本号,对节点的写请求都会导致该节点的3种版本号增加 dataVersion(对znode数据的更改次数), cversion(对znode子节点的更改次数),aclversion(对znode ACL的更改次数)
    • ticks:当使用多服务器zookeeper时,服务器使用一个”滴答”来定义事件的时间,如状态上传,会话超时等,通过最小会话超时时间(默认是滴答事件*2)间接公开,如果客户端请求超过这个时间,那客户端就不能在连接上服务器端
  • 唯一视图,无论连接到哪个服务器,客户端都可看到相同的内容
  • 可靠性 数据的变更不会丢失,除非被客户端覆盖修改
  • 及时性 保证系统的客户端当时读取到的数据是最新的

zookeeper理论

会话机制

  • 一个客户端连接一个会话,由zookeeper分配唯一会话id
  • 客户端以特定的时间间隔发送心跳以保持会话有效,超过会话超时时间未收到客户端的心跳,则判断客户端无效(默认2倍tickTime)
  • 会话中请求时FIFO(先进先出原则)的顺序执行

    znode的数据构成

  • 节点数据:存储的基本信息(状态,配置,位置等)
  • 节点元数据:stat命令下的数据
  • 数据大小:限制1M

    znode节点类型

  • 持久节点: 直接通过create path value创建
  • 临时节点:create -e path value
  • 顺序节点:create -s path value

注:

  • session会话失效时,临时节点就会被删除
  • 顺序节点的创建,每个父节点拥有一个计数器,这个计数器是有限制的,2147483647之后将溢出
  • 顺序节点在会话结束后仍存在

Watch监听机制

客户端能在znodes上设置watch,监听znode的变化,包括增删改查,通过stat path,ls2 path get path皆可查看
触发watch事件的条件有4种,create,delete,change,child(子节点事件)

监听步骤

  • 任何session(s1、s2)都可以对自己感兴趣的znode监听

  • 当znode通过s1对节点进行了修改

  • s1、s2都会收到znode的变更事件通知

注意:

  • 仅一次性:watch触发后删除,要持续监听的话需要持续提供设置watch

  • 有序性:客户端先得到watch通知才可以查看变化结果

  • 一个watch对象只会被通知一次,如果一个watch同时注册了多个接口,如果此时删除节点,这个事件对多个接口都有效,但是watch只会被调用一次

zookeeper拥有的功能

监视节点、通知进程、保持长连接、会话延续

zookeeper应用场景

注册中心

zookeeper作为注册中心

  • 依赖于临时节点
  • 服务提供者启动时,将服务名称,ip地址注册到配置中心
  • 服务消费者启动的时候,会先去注册中心中全量拉取服务的注册列表,缓存到本地,当消费者调用服务时,不会再去请求注册中心,直接通过负载均衡算法从ip列表中取出一个ip进行调用
  • 当服务提供者下线(上线),相应的ip会从服务提供者列表中移除(新增),注册中心会将服务ip列表发送给服务消费者,刷新缓存
  • 感知服务上下线(心跳检测,定时向服务提供者发送请求,确认是否在线)

注册中心对比

关系型数据库遵循的原则:ACID原则 (A:原子性 C:一致性 I:独立性 D:持久性)
非关系型数据库遵循的原则:CAP原则 (C:强一致性 A:可用性 P:分区容错性)

Eureka保证AP
zookeeper保证CP

分布式协调

以mq举例,A系统发个请求到mq,B系统消息消费之后处理了。A系统如何知道B系统的处理结果?
使用zookeeper实现分布式系统之间的协调工作。A系统发送请求知乎可以在zookeeper上对某个节点的值注册个监听器,一旦B系统处理完了之后就修改zookeeper那个节点的值,A系统就可以收到通知

分布式锁

  • 依赖于临时顺序节点
  • 三个系统A/B/C都去访问locks节点,访问的时候会创建带顺序号的临时/短暂节点,(例如,A创建了id_0000节点,B创建了id_0001节点,C创建了id_0002节点)
  • 拿到/locks节点下的所有子节点(id_0000,id_0001,id_0002),判断自己创建的是不是最小的节点
  • 如果是,则拿到锁,执行完操作之后,把创建的节点删掉,即为释放锁
  • 如果不是,则监听比自己小1地节点变化,发现比自己小1的节点删掉之后,发现自己已经是最小的节点了,拿到锁

另一种方式
对某数据连续发出两个修改操作,两台机器同时收到了请求,但是只能一台机器先执行完另一个再执行。使用zookeeper,一台机器接收到请求之后先获取zookeeper上的一把分布式锁(创建一个znode),接着执行操作,另一个机器也尝试去创建那个znode,发现自己创建不了,因为别人已创建,等第一个机器执行完之后再执行。

集群管理与master选举

  • 依赖于临时节点
    感知节点变化来获取集群状态
    如系统A、B、C,在集群groupMember下挂三个临时节点A、B、C,只要A系统挂掉,groupMember/A节点就会删除,通过监听groupMember下的子节点,B、C系统就可以感知到系统A挂了
    除了感知节点上下线变化之外,zookeeper还可以实现动态选举master功能(主从架构下)
    zookeeper每次选举最小编号的作为master,如果master挂了,对应节点删除。然后让最小的编号节点做为master,这样就可以实现动态选举功能了。

可切换主备,主挂了通过zookeeper感知切换到备。

统一配置管理

将公共配置放在zookeeper的Znode节点中,各个系统监听这个节点有无变更,如果变更了,及时响应

统一命名服务

为某一部分的资源进行命名,别人通过这个名字就可以拿到对应的资源了

ZAB协议

zookeeper采用的ZAB协议(ZooKeeper Atomic Broadcast,ZooKeeper原子广播协议),基于ZAB协议,zookeeper实现了一职中主备模式(Leader、Follower)的系统架构来保持集群中各副本之间的数据一致性
zookeeper中有三种类型的节点leader、follower、observer(follower、observer属于learner)
分为三个步骤

  • Leader包装写请求,生成唯一zxid,发起提议,广播给所有Follower
  • Follower收到提议后,写入本地事务日志,根据自身情况,是否同意该事务的提交
  • Leader收到过半的follower同意,自己先添加事务。然后对所有的learner节点发送提交事务请求

如果leader挂了之后,会从follower中选举(谁的数据最新,谁就有优先被选为Leader的资格)比较事务id