zookeeper

我们都知道zookeeper 是分布式协调框架,kafka 这些都会依托于zk来存储元数据
zk 要了解他的数据结构以及监听机制,这个才是他能够作为分布式协调框架最核心的功能
zk是比较典型的CP架构
zk是很早的分布式协调框架 相当于分布式协调框架的鼻祖 现在已经有很多的方案 比如说etcd
zk的作用主要是保证我们的一致性 特别是我们的强一致性
大概是怎么实现的  以注册中心为例

在这里插入图片描述

我客户端要拉取我们的服务端列表,同时我也要获取到最新的服务列表
因为有些服务可能出问题了,宕机了,我客户端可以感知到这种变化
这个时候需要我们服务发现的组件(我们的注册中心)
zk可以作为注册中心,他是怎么去做的,zk可以当作注册中心 他是怎么去做的
1.提供一个注册功能(类似于文件目录的方式),在我们中间有3个子节点  service1、service2. service3,节点是可以存储数据的  (比如说他的ip :port)
这首先是他的第一个功能,是存储的功能,而且是基于我们的树型结构,类似于linux文件系统的目录结构
可以把有那些服务对应的端口ip 都进行存储, client就可以从我们的集群中 可以通过接口
查到service下面有那些节点 有那些服务

在这里插入图片描述

但是我们服务发现最重要的是可以感知我们的服务是否有异常  比如说你宕机了 此时宕机是不可以用的 要把这个剔除
有个监听机制,意思是我们可以对zk的这个节点进行监听(注册成为一个临时节点)
只要你down机了就断开连接了,断开连接的话,他这个临时节点会自动删除了
他有个观察者模式 我监听到这个节点down机了,我就可以通知我客户端  告诉客户端是down机了


1.存储是按照文件系统的方式进行存储的
2.他对每个节点是有监听机制的, 可以监听节点中数据的变化
这就是zk, 基于zk的功能我们可以实现
搭建zk环境  我这边基于docker搭建的,
可以看这里https://blog.csdn.net/zhuganlai168/article/details/130224626 
zk他如果作为配置中心或者注册中心他和nacos功能是差不多的
nacos 也是做注册中心和配置中心的  这个就是zk的默认文件夹

在这里插入图片描述
在这里插入图片描述

启动客户端  启动服务端 然后 可以看到zk 默认使用的是zoo.cfg 的文件进行启动,这样的化我服务就起来了,像文件夹一样的目录

我们既然像linux 文件系统一样   我们可以通过Ls来看


在这里插入图片描述

我们就可以基于zk做CURD 操作

在这里插入图片描述

比如说我的create操作,我可以创建一个节点,
我可以给这个节点设置一个值,我可以给这个节点获取一个值
我还可以在lvhao 后面继续创建子节点

在这里插入图片描述
在这里插入图片描述

crud 有点像我们的redis  创建一个节点 删除一个节点
这是一个基本操作
关键是zk 有几种节点  以及他的监听机制
以及我们可以利用他的监听机制干一些事情,zk这么一个结构   
其实就类似我们这种Linux系统的这种结构

在这里插入图片描述

我比如说我监听/app1,我就可以知道他的子节点有没有新增,有没有减少,
我只要监听 /app1的话,你新增一个子服务,或者删除一个子服务的话 我都可以感知到,
这就很方便,这是他的一个结构类似于文件系统的层次结构,而不是单纯像redis 一样这种key value 
因为他考虑监听

在这里插入图片描述

 get -s /lvhao  我们可以通过 这个命令来查看节点的状态

在这里插入图片描述

zk的节点分临时和持久节点
持久节点 创建之后一直存在
临时节点 临时节点,一旦和我们服务端断开连接 就会被del  所以服务注册都是临时节点,
我可以基于zk的临时节点去做分布式锁    因为临时节点创建之后 再来一个客户端是创建不了的

在这里插入图片描述

我当前线程想创建这个临时节点,一个线程过来创建的节点,我另外一个线程也想创建这个临时节点
就是你创建完了,你lock节点已经存在了,他其他线程肯定是不能,其他线程去创建了lock锁的
他会提示你已经存在, 因为这个节点已经存在了 所以会失败
我们可以基于这个功能实现分布式锁
临时节点的特点 就是当我断开连接  他这个临时节点就会删除.当我们会话超时或者发生异常的时候 临时节点他也会被干掉


也就是说加锁的时候,如果我服务意外宕机了,没有正常释放锁,他 此时会断开连接,我就可以避免我程序死锁,
呢其他线程怎么知道你锁什么时候释放,我加锁失败了就会阻塞我什么时候知道我可以去尝试
我们可以用 stat -w /lock 这个命令来监听,一旦第一个线程delete这个锁的时候
我们就可以监听到这个锁释放了.继而就可以去做我们的业务逻辑了

在这里插入图片描述

我可以开启针对于这个节点的监听,如果那边释放锁,我就可以监听到,继而继续create -e /lock加锁
通过这个临时节点,我就可以实现独占锁.
我创建一个节点,尝试获取这个锁,我就可以获取这个锁,失败的话,我就去监听这个锁,当我监听到这个锁
释放了的话, 我就可以继续加锁
临时节点的特性:客户端超时 或者是发生异常 意外的终止 会话结束了他这个节点就会删除	 这样以来我们如果利用在锁的场景下 我们可以避免死锁
持久节点他就会一直存在  他会有一个有序节点
有序节点的特点  一般我们会创建一个临时有序的节点

在这里插入图片描述

我们可以根据这个有序节点的特性来实现分布式唯一自增Id,如果我创建这个临时节点是有序的  他不会提示我节点冲突
有序 -s
https://blog.csdn.net/zxf126126/article/details/127993071 [zk的数据写入半数机制]
zk如果从集群看的话 他是强一致的,比如说我们set (key,value),如果他是集群的话,会有个过半机制
如果有大多数节点响应 的话,才可以提交.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

当我们对节点set值得时候 mZxid  就会更新,而且版本号也会加1 ,当我们基于当前节点去创建子节点得时候,pZxid 就会发生变化(此时数据得版本号不会改变)
ZK的节点 有
cZxid = 0x4  创建节点的事务Id
mZxid = 0x5 
pZxid = 0x6

在这里插入图片描述

我们可以基于zk的版本号机制实现乐观锁

在这里插入图片描述

zk的监听机制,就是说 我可以监听某个节点的变化(zk的watch机制)

在这里插入图片描述

例如数据节点发生变化了, 我们就可以监听到,继而就可以做我们自己的操作了
我们可以利用zk的监听机制实现类似于k8s可以自动检测服务并且拉服务的这种模式.系统中只能有一个master , master能实时获取系统中worker的情况。
比如说 我master节点监听worker变化,如果worker宕机的话, 我重启一个就好了。
类似于k8s 一样当一个节点出问题之后。我可以自动启动起来 可以实现自动转移
借助于zk我就可以实现。我把这个元数据信息 我存储在zk 中存储起来
他就可以记录master 以及worker进程状态
当 发现有变化的时候 比如说worker挂了  我就可以感知到 继而去做处理
他就可以监听到worker 进程挂了 我回调方法我再去启动一个worker进程就可以了
我们用zk 用的就是他的临时节点以及持久节点以及临时有节点,还有这些节点的特性以及watch机制
这些基本可以满足我们的日常业务需要

在这里插入图片描述

这是上述zk中节点的特性,我们依据于他的节点特性就可以看到zk的应用场景

在这里插入图片描述

zk的集群架构  我们都知道zk的集群中分Leader,Follow,Observer角色,
CAP 架构我要保证的强一致性,
同步到过半机制的节点,保证过半机制的节点访问成功了 我写入就可以了
写数据的时候要保证大部分节点都成功
因为这样的时候即便主节点挂了 我选举的时候 他选举的时候 会以有最新数据的节点去选举主节点
observer:可以不参与投票  提供读数据


在这里插入图片描述

leader收到大多数的ack  我就commit提交 
leader会吧数据同步给ob节点
observer节点会存储数据的  对于客户端的话 我从ob上读数据
所有客户端发送的读请求都可以发送到Leader observer follow节点上,  但是发送的写请求只能发送到
Leader上,即便是发送到follow上的话,也需要转发到Leader上

ZK的集群的搭建

在这里插入图片描述

在这里插入图片描述

我第二台机器上是Leader,如果我此时重启之后 他就会进行选举,我们此时leader节点就变化了

在这里插入图片描述
在这里插入图片描述

我们可以看到他的集群信息,
zk中我们要了解 节点类型 临时节点  持久节点  临时有序节点的特性
临时节点 断开连接 节点删除
监听机制 利用节点特性加上监听机制我们可以实现很多功能
zk的节点特性和监听特性,基于zk的节点以及监听机制我们可以实现很多功能,比如说
发布订阅,分布式配置中心之类的
我们之前都是基于命令行来操作我们的zk的crud,我们现在可以基于java代码来操作我们的crud
这是之前 所讲的  创建节点 创建子节点  然后去监听节点的数据变化
他都可以监听到

在这里插入图片描述

我们Java实现zk 客户端基本上有2种
一种是原生的
一种是第三方的

在这里插入图片描述
在这里插入图片描述

zk原生官方的api 比较简单,比如说一些中间件 Kafka或者大数据之类用的zk,包括dubbo2.x版本都引入了对应zk的版本,他们一般就会用这2钟客户端来操作zk
呢么原生的api怎么去用,导入jar,
我们怎么去使用 我们要去创建一个节点 去监听这个节点 去给这个节点set数据
我们要怎么去做

在这里插入图片描述

基于api 操作就可以了 我创建一个节点,然后我添加一个watch来监听这个节点,我只要我的值发生变化  我监听器,我就可以发生变化,监听到我就可以做处理

在这里插入图片描述
在这里插入图片描述

我客户端就可以拉取我最新的服务端数据进行缓存
我更新的时候 我可以带一个版本号来更新,这样就可以实现乐观锁更新了

在这里插入图片描述

curator,我们使用分布式锁的话 我们直接使用这个框架就可以了,
一样导入jar就可以,我可以对节点进行监听.子节点的事件子节点的添加,子节点的删除,子节点的数据改变的事件 都是可以帮我们监听到
我可以感知节点的变化 我就可以进行通知
这就是客户端的使用

在这里插入图片描述

假如我这个配置中心  我对他做了改变之后 ,我watch机制就可以做到监听到 然后我就可以变更我本地数据

在这里插入图片描述

我都可以感知到 节点的数据变化
我基本功能我只需要感知到 crud  以及监听就可以了
在配置中心中,当我配置发生改版的时候,我要实时感知他的变化
@refreshscope 注解   配置的动态刷新
zk可以存储1兆的数据,当数据发生变化的时候,我监听这个节点就可以感知到
我来监听这个节点的数据变化 如果数据发生了变化 我来拉取最新的数据

在这里插入图片描述

我本地服务通过zk的监听机制 我就可以感受到我配置发生改变了,我们就可以利用zk 来存储元数据信息
比如说服务的配置(元数据存储在配置中心中)关键是你要感知到元数据的变化
如果没有zk的watch机制,我就需要自己去做的话我的搞一个轮询不停的去拉取配置中心的数据,但实际上
我现在基于zk的watch机制 我就可以实现推拉结合的模式,如果注册中心中元数据发生变化
他会进行推送的  服务端 可以推送 

在这里插入图片描述

推拉结合
所有中间件中最本质的感受数据变化的  常用的方式
nacos配置中心也差不多 ,当配置中心发生数据变化的时候 他会进行推送,推给对应的微服务
在zk中创建一个节点.然后去监听他  发生改变之后 我做出对应的处理
zk的最大优势 有节点的特性以及监听机制 我们就可以干很多事情
我们来看下常用的场景

在这里插入图片描述

比如说dubbo中基于zk进行存储的元数据信息
我userService----->orderService 我是基于接口发起的请求
但是我 userService 调用orderService的时候 我要感知他orderService 后面集群有几个
我就可以订阅这里的orderService服务,也就是说 我userService ---->orderService 的时候
我就可以感知到服务的上下线

在这里插入图片描述

我们可以基于zk 把我们的服务进行暴露。利用这些元数据信息我们dubbo 就可以实现元数据发现
服务注册的时候是临时节点(当服务down机的时候) 我再拉取服务的时候 我就拉取不到了
因为临时节点的特性,现在主流的是Springcloud这一套
Kafka也是也是有这个元数据信息要存储在zk中


zk的这种 动态上下线的通知,上线就会增加,下线就会剔除
这样以来对于我系统调用者来说是没有感知的,
我每次只是拉取你的服务  你那边减少了 ,就通过zk的watch机制通知我就可以了
利用zk来做是很方便的

就类似于访问baidu ,后面对应的ip 集群  ,当后台有一个节点down机后 我watch机制就可以进行监听到
分布式id 在分布式架构中这些是一定要去实现的
分布式id 的应用场景
1、 分库分表
比如说链路追踪 多个服务公用一个链路追踪Id
2. 分布式事务我开启全局事务的时候,我userService服务和OrderService服务 我全局事务Id

我们要考虑这些全局唯一id 的高可用的话 我们也要考虑对应的性能


我们可以
1. uuid
2. redis 自增incr
3.zk的顺序节点 也是可以生成id
4.雪花算法

但是uuid肯定是不太合适的 因为基于mysql的B+树考虑的

在这里插入图片描述
在这里插入图片描述

有序的id, 我们基于zk 来实现全局Id
全局唯一id 的方案还是挺多的
利用有序的节点  就可以直接生成
这就是zk的应用

在这里插入图片描述

zk也可以做分布式队列  基于他的顺序节点

在这里插入图片描述

这个就是一个很典型的队列,队列中先进先出 我们只要拿到最小的就可以
zk可以做分布式队列,每一个节点存储最大1兆数据,他就不能存储大量数据
因为如果数据量太大的话, 我做集群数据同步的时候就会耗时 就会有带宽的限制
贷款就会成为他的瓶颈

分布式栈 最小的出栈 就可以了 ,其实底层本质就是有序节点实现的,对于zk来说
我可以实时感知到节点的变化,我zk 我只要监听这个节点
只要一挂 我消费者的感知是实时的
nacos 会有一些延迟, 因为他是基于心跳的 服务的续约做的
服务续约,会记录下你当前续约的时间,如果没有发送心跳,我就会把你的服务进行剔除
zk 是基于watch机制做的

对于zk来说,只要监听节点就可以了,我节点挂了 我立马就会感知到,直接基于watch机制来进行推送
动态感知服务的上下线,使用zk还是有优势的

如果对感知要求不高的情况下可以使用nacos,如果要求较高的话 使用zk会更好,这是注册中心选型要考虑的东西
我们主要要了解zk的节点特性以及watch机制
如果以后要做这种动态监听感知数据变化的场景   可能动态感知服务的上下限 都可以使用zk来做

在这里插入图片描述

1.分布式锁 2. 注册中心
多线程情况下,会存在锁的竞争,sy lock锁,解决多线程资源访问的情况,
分布式场景下就要使用分布式锁

1. 分布式锁的主流解决方案

在这里插入图片描述

1.数据库锁  可能会出现锁表的情况下 利用数据库的唯一索引
2.基于redis实现的分布式锁 redis 的setnx 会有很多问题 用redission来做  redsiion的看门狗机制  因为redis的lua脚本是原子性的,
3.基于zk实现的分布式锁

如果你的应用场景并发高,要求性能能好一些就可以使用redis分布式
我们也可以基于zk的临时节点来做,防止死锁的情况


zk的话 对数据一致性要求高一些,对性能要求不是很高,如果你的业务场景并发量不是很高  可以采用使用zk来做

我们使用zk可以避免死锁,因为临时节点的特性,就可以避免死锁,这种就不会有mysql的死锁 出现
因为他是临时节点,临时节点的特性就是会话结束 我的临时节点就被干掉了
天然避免死锁的问题

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在高并发的时候假设这一秒 有1oo个线程过来抢锁  只有一个线程获取锁 其余线程就会在等待
99里面只会有一个竞争成功
这对我们系统来说是个负担  大量线程在做无用功  我不停的等待唤醒
基于这种问题 AQS 怎么做的 我有大量线程过来  一个线程成功了 其他线程失败了
专门有一个同步队列  我这个线程入队之后再阻塞
我只需要唤醒第一个
我只需要唤醒队首 的这一个就可以了


zk的临时有序节点就有分布式队列的特性 ,我们不用再去这个分布式队列了
我们可以用他的临时有序节点实现这个功能
所以此时需要一个队列 我只需要监听我上一个节点是否释放锁就可以了


在这里插入图片描述

zk的监听watch机制,我们只需要监听当前这个节点的上一个节点是否释放锁就可以了,这样就可以实现我们的分布式锁的逻辑了


我们很多时候 读多写少的情况下 我们可以使用读写锁来降低锁的 颗粒读

在这里插入图片描述

你 不论是服务挂了还是主动删除了 他都可以监听到
因为节点是临时节点  这就是zk 防止死锁\

https://blog.csdn.net/qq_33371766/article/details/129827557  coding 


关于我们zk的分布式锁,如果你的应用场景是高并发,并发量比较大的 可以使用redis分布式锁
如果并发量不是很高 mysql 或者zk就可以

在这里插入图片描述

我们的zk还可以做注册中心,就是实现我们的服务注册和发现, 基于zk实现的注册中心

在这里插入图片描述

注册中心的逻辑 
1. 服务启动需要Insert到zk中
2. 我发起调用的时候 需要从注册中心获取到对应服务的数据
3. 如果B 宕机后 我A 需要基于watch机制感知到


zk 是基于watch机制 观察服务的上下线
nacos基于心跳服务续约机制
我基于注册中心获取信息 然后基于lb 发起调用

在这里插入图片描述

我服务的上下线,我基于watch机制就可以感知到
springcloud 整合zk
我吧我服务注册在zk上.上面有他的信息 比如说ip:port
可以实时感知到服务的上下线
这就是zk作为注册中心的好处
1、使用zk  数据不能过多 2. 节点不能过多
因为数据同步 要耗时  大部分提交之后 我才能告诉客户端 是可用的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值