1、为什么需要ZooKeeper?
(1)现代应用需要分布式部署
- 单台计算机性能升级无法支撑日益庞大的数据量
- 容错容灾考虑
(2)在分布式应用场景中,开发和运维人员耗费大量时间处理异构系统的协作通信问题
(3)ZooKeeper专门应用分布式系统协作通信,使得开发人员专注业务逻辑
2、Zookeeper架构图
(1)生产环境用ZK集群,一般有奇数个ZK节点组成(选举Leader需要半数以上达成一致),每个ZK节点都存储一份相同数据
(2)ZK集群启动后,选举出一个Leader(使用Paxos协议),其它节点自然成为Follower
(3)数据更新请求由Leader处理,并且Leader会把数据更新广播给所有Follower,只有半数以上Follower更新成功,Leader才会提交更新,此时代表数据更新真正成功(Zab协议)
(4)当Leader发生故障,会触发集群重新选举,某个Follower成为新的Leader,如之前Leader恢复,则自然成为Follower
3、zookeeper基本元素
(1)znode类型
- PERSISTENT--持久化目录节点:允许有子节点,只能通过调用delete来删除
- EPHEMERAL-临时目录节点:不允许有子节点,当创建该节点的客户端崩溃或关闭了zookeeper的连接时,该节点就会被删除
- PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点:断开连接节点仍在,zk会进行顺序编号
- EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点:断开连接节点删除,zk会进行顺序编号
(2)znode读写
注意:zookeeper不允许局部写入或读取znode节点中的数据,而只能整个替换或全部读取
(3)监视与通知
Watcher机制:客户端向zookeeper注册监听某个path,该path子节点有事件(ADD/UPDATE/DELETE..)发生会通知
(4)版本
- 每个znode都有一个版本号,随着每次数据变化而自增
- 使用版本来阻止并行操作的不一致性
4、ZooKeeper应用场景
(1)作为RPC注册中心
(2)分布式锁
什么是分布式锁?
类比进程内的锁:syncronized,reentrantlock
前提很重要,在分布式部署场景下,多个服务(进程)操作同一份资源,需要一把锁保证资源操作正确性,例如用户填写表单,理论上只能有一个服务提供者能够写入
>>>使用zookeeper实现
- 创建一个持久化节点/lock,代表一个分布式锁
- 需要获取锁的客户端在/lock下创建临时顺序节点
- 比较/lock下所有子节点大小,最小则获得锁,使用完则删除当前节点
- 如果某个客户端没有获取到锁,则监听前一个顺序节点,如果收到前一个顺序节点删除事件,则重新比较节点大小,最小则获得锁
- 如何防止死锁?当持有锁的客户端挂掉,虽然没有手工删除节点,由于ZK心跳机制,也会自动删除有问题的客户端
>>>使用redis实现
- 为什么可以使用redis?Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系
- 如何防止死锁?(创建锁客户端崩溃?)创建锁时设置过期时间
- 使用命令:setNx(SET if Not eXists)
>>>>二者使用场景区别
高性能,高并发:使用Redis,因为zk每次创建/删除节点不能保证响应时间