Zookeeper是什么
Zookeeper开源的分布式的, 为分布式框架提供协调服务的Apache项目
是一个基于观察者设计模式的分布式服务管理框架, 会接受观察者的注册, 当数据的状态发生了变化, Zookeeper就会负责通知已经在Zookeeper上注册的观察者做出对应的反应
- 类似手机的日程提醒, 当时间到达的时候日程提醒就会发送通知告诉我们事件发生了
Zookeeper特点
-
一个领导者Leader和多个追随者Follower组成的集群
-
集群只要有半数以上的阶段存活就能正常提供服务
此处推荐奇数部署, 用于投票机制并且保证可靠性
-
全局数据一致, 每个Server都会保存一份相同的数据副本, Client无论连接到那个Server获取的数据都是一致的
-
更新请求会顺序执行来保证数据一致性
-
支持原子操作, 数据更新是原子性的
Zookeeper如何存储数据 | Zookeeper的数据结构
- 是一个树形的结构, 每个节点都被称为一个ZNode, 每个节点只能存储1mb数据
- 每个节点都通过其路径唯一标识
- 每个节点要访问到的路径都是唯一的, 所以可以通过路径来唯一标识一个节点
- 因为存储的数据量小, 所以zookeeper不适合存储海量数据, 适合存储配置信息一类的数据
Zookeeper可以提供的使用场景
-
统一命名服务
类似为域名配置多个IP, 就是提供一个地址注册中心的服务 -
统一配置服务
集群中一般要求节点的配置信息是一致的, 比如Kafka集群, 当对配置文件修改后要快速同步到每个节点上, 这里就可以交给Zookeeper去配置
通过将配置信息写入到Zookeeper中的某个节点, 每个Zookeeper客户端监听该ZNode来获取配置信息的更新操作 -
统一集群管理
Zookeeper可以实时监控集群中节点的状态变化
通过将节点信息写入到ZNode中, 让客户端监听该节点来获取实时的节点状态变化 -
服务器节点动态上下线
提供一个服务器注册中心的功能, 将zookeeper作为一个注册中心, 通过使用临时节点的功能来检测服务器的上下线
当出现服务器的下线时间的时候客户端就可以根据业务调整负载均衡的策略来动态调整 -
软负载均衡
可以通过zookeeper节点来记录每个服务器的访问次数, 通过这些访问次数来动态调整负载均衡策略
讲讲基于Zookeeper的分布式锁实现方案
基本思路
通过订阅在zookeeper集群中的某个节点的变化来实现的加锁和解锁通知
- 下面zookeeper简称ZK
加锁思路
- 加锁的服务器往ZK中的节点
/lock
添加一个节点
- 注意该节点是临时的带序号的
- 使用临时节点是用于在加锁服务器掉线的时候自动解锁, 带序号是用于对加锁的服务器进行排序, 方便按顺序获取锁
- 然后获取
/lock
下的所有节点, 如果当前只有服务器添加的这个节点则返回加锁成功 - 如果获取到的节点数量大于1, 就对获取到的节点进行排序, 排序后如果服务器添加的节点是排序后数组的第一个节点则加锁成功
- 如果服务器添加的节点不是第一个, 就订阅当前节点的上一个节点, 然后阻塞等待前一个节点锁释放节点被删除
- 如果前一个节点刚好被删除无法订阅, zookeeper会报异常, 此时通过异常捕获返回加锁失败让业务逻辑重新尝试加锁即可
- 当前一个节点释放后, 会通过ZK的回调线程回调, 服务器需要在回调函数中进行唤醒操作
- 此处应该使用同步操作来实现, 通过信号量为1的同步锁来实现等待锁和唤醒功能
- 当前一个节点被删除, 注册的回调函数会唤醒线程返回加锁成功
解锁思路
- 将加锁的时候添加的节点删除即可
- 在等待获得锁的成员会由zookeeper的通知和注册的回调函数来负责解锁
- 对于服务器下线的情况可以利用临时节点的自动删除策略来防止锁没有释放整个系统阻塞
总结
zookeeper是保证数据一致性和分区容错性的一个中间件, 因为其高可靠性可以作为服务器的注册中心或分布式锁的底层实现来部署使用, 现有的企业也提供了很多现成的基于zookeeper实现方案, 比如Clustor这个分布式锁方案
所以入门学习zookeeper主要还是了解节点操作的逻辑和订阅功能为主, 掌握好使用方式即可