
本文共 12479 字,大约阅读时间需要 41 分钟。
文章目录
zookeeper环境搭建
linux下jdk环境搭建
一、安装jdk
1、将jdk和zookeeper通过ftp转移到linux /home下
2、解压jdk和zookeeper到/usr/和/usr/local下
解压jdk和zookeeper
tar -zxvf ....jdktar -zxvf ...zookeeper
修改解压之后的jdk和zookeeper的名字
mv XXX jdk8mv YYY zookeeper
转移jdk和zookeeper
mv jdk8 /usrmv zookeeper /usr/local
2、配置jdk和zookeeper环境变量
修改配置文件 vim /etc/profile
export JAVA_HOME=/usr/jdk8export ZOOKEEPER_HOME=/usr/local/zookeeperexport CLASSPATH=.:%JAVA_HOME%/lib/dt.jar:%JAVA_HOME%/lib/tools.jarexport PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin
配置完环境变量测试一下是否成功
测试之前先刷新配置文件
source /etc/profile//测试java -version
二、zookeeper配置文件
复制zookeeper/conf/zookeeper.cfg文件
cp zookeeper.cfg zoo.cfg
1、tickTime
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔。 也就是每隔 tickTime 时间就会发送一个心跳。以毫秒为单位,比如session超时 N*tickTime
2、initLimit
用于集群,允许从节点链接并同步到master节点的初始化连接时间,以tickTime的倍数来表示。
3、syncLimit
用于集群,master主节点与从节点之间发送消息,请求和应答时间长度(心跳机制),超时从节点就会被抛弃
4、dataDir
必须配置
但是不能配置到临时文件夹里面 dataDir=/tmp/zookeeper 修改为 dataDir=/usr/local/zookeeper/dataDir dataLogDir=/usr/local/zookeeper/dataLogDir5、dataLogDir
日志目录,如果不配置会和dataDir公用
6、clientport
连接服务器的端口,默认2181
三、启动zookeeper
//启动./zkServer.sh start//重启,现关闭再开启./zkServer.sh restart//查看状态./zkServer.sh status
3-1 zk数据模型介绍
1、树形结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ygF1mlkK-1575608668526)(en-resource://database/1749:1)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djztQuLN-1575608668527)(en-resource://database/1751:1)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vc99c9ml-1575608668528)(en-resource://database/1753:1)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YGV94rXQ-1575608668528)(en-resource://database/1755:1)]3-2 zookeeper数据模型的基本操作
- 客户端连接 ./zkCli.sh打开命令行后台 连接到Connecting to localhost:2181 Ctrl+C退出当前客户端
- 查看znode结构
- 关闭客户端连接
3-3 zookeeper的作用
1、高可用,当master挂了之后,后续的从节点就会替补上去,不让让系统崩掉,这也叫做首脑模式,保证集群的高可用,高可用的体现之一,局长死了,副局长立马顶上
2、统一配置文件管理,只需要部署一台服务器,则可以吧相同的配置文件同步更新到其他服务器,此操作在云计算中非常多(假设修改了redis统一配置) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZGMp7qyF-1575608668529)(en-resource://database/1757:1)] 3、发布与订阅,例如消息队列MQ,发布者将信息发布到节点,二订阅了节点的订阅者就会收到这个信息,相应的进行改变 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ic7PjXA0-1575608668530)(en-resource://database/1759:1)] 4、提供分布式锁,分布式环境中,不同进程的资源争抢,类似以多线程中的锁(为什么zookeeper能提供分布式锁呢,归因于zookeeper的结构,在zookeeper的结构中,增加节点是往后续的,即一个个增加在后面,类似于队列,所以第一个就是相当于master,这个唯一就是锁) 5、集群管理,集群保证数据的强一致性 比如客户端连接了主节点,并且增加数据Data-XYZ,那么由于集群的机制会进行同步,那么从节点酒也有了这个数据,客户端断开之后,连接其他节点也会读到相同的信息(类似于2统一文件-配置) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xgLMpyzY-1575608668530)(en-resource://database/1761:1)]4-1 zookeeper的常用命令
- ./zkCli.sh 打开命令行后台
- ls和ls2 ls查看目录 ls /zookeeper ls2是查看节点状态信息 ls2 / ls2相当于ls和stat
- stat 查看状态信息
- get 当前节点的数据取出来 czxid 节点创建的id ctime 节点创建的时间 mzxid 节点修改的id mtime 节点修改的时间 pzxid 子节点的id cversion 子节点的版本 dataVersion 数据的版本 aclVersion 节点权限修改的版本 ephemeralOwner 之后再说 dataLength 数据长度 numChildren 下面子节点的个数
4-2 session的基本原理
基本原理一
- 客户端与服务器之间的连接存在会话
- 每个会话都会可以设置一个超时时间
- 心跳结束,则Session过期 因为每个心跳都会向服务器发送一个(ping包?)信息,从而保证服务器知道session还活着
基本原理二
- Session过期,则临时节点znode会被抛弃
- 心跳机制:客户端向服务器的ping包请求
创建节点
创建默认节点(持久存在)
create /imooc immoc-data
创建临时节点(断开连接后,心跳结束不存在)
cerate -e /imooc/tmp tmp-data
如何识别是临时节点?
不是临时节点:ephemeralOwner=0x0 是临时节点::ephemeralOwner=0x0… 当zookeeper连接关闭时,临时节点不会立马被删除,临时节点默认存在一个心跳时间,等这个时间过后才会被删除创建顺序节点(持久存在)
create -s /immoc/seq seq-data
ls /imooc [seq0000000001]
创建的顺序节点从1开始
create -s /imooc/seq seq-data
ls /imooc [seq0000000001, seq0000000002] 创建时节点序号是依次递增的修改节点
set [-s] [-v version] path data
set /imooc new-data 修改之后,mtime、dataVersion、dataLength就会发生变化
dataVersion递增1在指定版本号的节点,进行修改的情况
①、set -v 1 /imooc new
②、set -v 1 /imooc new
发生错误version No is not valid : /imooc
原因是①更新节点之后,dataVersion自增1变为了2,②更新的时候版本号已经不是1了,所以才会导致版本号不可校验,这可以做到乐观锁的效果,所以在并发的时候,由于版本号的问题,就不会导致并发错误所以只能修改最新版本号的节点(不加版本号,默认修改最新版本的节点),修改其他版本的节点,就会出错
删除节点
delete [-v version] path
其他问题同上述修改节点
4-3 zk特性 watcher机制
一:
- 针对每个节点的操作,都会有一个监督者→watcher
- 当监控的某个对象(znode)发生变化,则触发watcher事件
- zk中的watcher是一次性的,触发后立即销毁
二:
- 父节点、子节点都能触发watcher
- 针对不同的操作,watcher能表现不同的反应 (子)节点删除事件 (子)节点修改事件 (子)节点变化事件 当(子)节点发生变化时,触发watcher相应的事件,客户端在收到这个事件之后,比对事件名,然后做出自己的操作,比如节点发出删除事件,watcher发送给客户端,客户端接收到这个事件之后,匹配成功,然后再删了与这个节点的连接
4-4 父节点watcher事件
- 创建父节点触发:NodeCreate
使用 stat [-w] path 为节点添加watcher
增加imooc节点的watcher stat -w /imooc 创建/imooc节点 create /imooc watcher-test WATCHER::WatchedEvent state:SyncConnected type:NodeCreated path:/imooc
- 修改父节点数据触发:NodeDataChanged
使用 get -w path为节点添加watcher
get -w /imooc set /imooc new-data WATCHER::WatchedEvent state:SyncConnected type:NodeDataChanged path:/imooc
- 删除父节点触发:NodeDeleted
使用 get -w path为节点添加watcher
get -w /imooc delete /imooc WATCHER::WatchedEvent state:SyncConnected type:NodeDeleted path:/imooc
4-5 子节点watcher事件
- ls为父节点(必须先存在父节点)设置watcher,创建子节点触发:NodeChildrenChanged
- ls为父节点设置watcher,删除子节点触发:NodeChildrenChanged
- ls为父节点设置watcher,修改子节点不触发事件 如果需要让子节点触发事件,那么就需要在这各自节点上设置watcher事件,触发NodeChanged事件
4-6 watcher使用场景
统一资源配置
4-7 权限ACL
ACL(Access control lists)权限控制
- 针对节点可以设置相关读写等权限,目的是为了保证数据安全性
- 权限permissions可以指定不同的权限范围以及角色
ACL命令行
- getAcl 得到某个节点路径的acl权限信息 getAcl path
- setAcl 设置某个节点路径的acl权限 setAcl path acl
- addauth 输入认证授权信息,注册时输入明文密码(登录)但是在zk的系统中,密码是以加密的形式存在的 addauth scheme auth
ASL的构成一
- zk的acl是通过[scheme🆔permission]来构成权限列表
scheme:权限模式,代表采用的某种权限机制,五种(常用四种)
id:代表允许访问的用户 permission:权限组合字符串
ACL的构成二 - Scheme
- world:world下只有一个id,那就是anyone,组合写法就是world:anyone:[permissions]
- auth:代表认证登录,需要注册用户有权限就可以,形式为:auth:user:password:[permissions]
- digest:需要对密码加密才能访问,组合格式为digest:username:BASE64(SHA1(password)):[permissions] auth与digest的区别就是:一个明文、一个密文、需要不同的访问方式
setAcl /path auth:lee:lee:cdrwa
setAcl /path digest:lee:BASE64(SHA1(lee)):cdrwa
一般auth用的不多,因为生产环境总是要加密的
addauth digest lee:lee 后都能操作指定节点的权限 4. ip:当设置为ip指定的ip地址,此时限制ip进行访问,比如ip:192.168.1.1:[permissions] 因为用的是集群,那么比如一个订单服务的ip是192.168.1.1,还有一个是192.168.1.2那么只有这两个ip可以访问这个节点,其他的比如报账服务就不能访问这个节点 5. super:代表超级管理员,拥有所有的权限,这个很危险,一般给运维或者研发经理或者CTO,所以一般不用,常用前四个4-8 acl的构成 permission的构成
权限字符串缩写:crdwa
- CREATE:创建子节点,不能创建节点
- READ:获取节点/子节点
- WRITE:设置节点数据
- DELETE:删除子节点
- ADMIN:设置权限
4-9 acl的命令行 world讲解
world:anyone:crawd
设置节点的权限
4-10 acl命令行 auth讲解
auth:user:pwd:crawd
digest:userBASE64(SHA1(pwd)):crawd addauth digest user:pwd
再给节点设置权限时,先登录,然后再给登录对象设置权限
addauth digest user:pwd
setAcl path auth:user:pwd:[permissions] getAcl path
4-11 acl命令行 digest讲解
登录和auth一样
addauth digest imooc:imocc
setAcl path digest:imooc:(imooc的密文):[permissions]
4-11 acl命令行 ip讲解
setAcl path ip:(ip地址):[permissions]
在之后的java客户端连接中,我们再来演示
4-12 acl之super超级管理员
场景:创建一个ipd能访问的节点,在这我们使用超级管理员账号去访问该节点
创建一个ip能访问的节点
create /names/ip xxx.xxx.xxx.xxx
setAcl /names/ip ip:xxx.xxx.xxx.xxx:crawd
修改配置文件,添加超级管理员账号
vim zkServer.sh
在nohup块中添加超级管理员账号密码(密文imooc,经过sha1和base64加密得到XwEDaL3J0JQGkRQzM0DpO6zMzZs=)
“-Dzookeeper.DigestAuthenticationProvider.superDigest=imooc:XwEDaL3J0JQGkRQzM0DpO6zMzZs=”\
重启zookeeper
./zkServer.sh restart
登录超级管理员
addauth digest imooc:imooc getAcl /names/ip如果没有登陆,或者登录的其他账号,则都不能访问该节点
4-13 acl的常用场景
- 开发/测试环境分离,开发者无权操作测试库的节点,只能看
- 生产环境控制指定ip的服务可以访问相关节点,防止混乱,由于有些是动态ip,有可能有点不方便
4-14 zk四字命令 Four letter words
- zk可以通过它自身提供的简写命令来和服务器进行交互
- 需要使用到nc命令 ,安装yum install nc
- echo [commond] | nc [ip] [port] 【stat】:查看zk的状态信息,以及是否mode 【ruok】:查看当前zkServer是否启动,返回imok 【dump】:列出未经处理的会话和临时节点 【conf】:查看相关配置信息 【cons】:展示连接到客户端的连接信息i 【envi】:环境变量,jdk,zookeeper等 【mntr】:监控zk的健康信息 【wchs】:展示watch的信息 【wchc与wchp】:session与watch及path与watch信息 注:如果报错例如: ruok is not executed because it is not in the whitelist.解决方法请看https://blog.csdn.net/x763795151/article/details/80599498
注:查看zookeeper事务日志
在配置文件zoo_sample.cfg中,事务日志和快照日志,默认在dataDir中 在配置了zoo.cfg之后,事务日志和快照日志分离,事务日志在在我们配置的dataLogDir中由于事务日志是二进制数据,因此用vi/vim不能查看得到,因此只能解码后查看
mkdir /use/log
cd /usr/local/zookeeper/lib cp slf4j-api.1.7.25.jar zookeeper.3.5.6.jar zookeeper.jute.3.5.6.jar /usr/logjava -classpath .:slf4j-api.1.7.25.jar:zookeeper.3.5.6.jar:zookeeper.jute.3.5.6.jar org.apache.zookeeper.LogFormatter /usr/local/zookeeper/dataLogDir/version-2/log.4e
1.创建一个文件夹log保存我们所需要的jar包
2.切换到zookeeper的lib文件夹下 3.复制所需要jar包到log中 4.编写解码信息 /usr/local/zookeeper/dataLogDir/version-2/log.4e 是我们的事务日志路径注:测试ookeeper版本为3.5.6
1、节点目录下有子节点,则父节点不能删除------父节点不能删除 2、如果节点是在/目录下且该节点没有子节点,不管有没有删除权限,任何的授权或者未授权用户都能删除该节点------根节点若没有子节点可以随便删除 3、如果该节点上一层且只能是上一层父节点,没有删除权限,则该节点不能被删除------本节点的父节点没有被删除的权限,则该节点也不能删除
5-1 zookeeper集群搭建
zk集群,主从节点,心跳机制(选举模式)
zookeeper集群搭建注意点
1.配置数据文件myid1/2/3对应server.1/2/3
2.通过./zkCli.sh -server [ip]:[port]检测集群是否配置成功5-2 单机伪分布式集群
单机的意思是在一台服务器上创建多个zookeeper节点,ip不见端口不一
创建额外的两个zookeeper节点
cp zookeeper zookeeper01 -rf
cp zookeeper zookeeper02 -rf修改配置文件
/usr/local/zookeeper/conf/zoo.cfg
vim /usr/local/zookeeper/conf/zoo.cfg
dataDir=/usr/local/zookeeper/dataDir dataLogDir=/usr/local/zookeeper/dataLogDir clientPort=2181 server.1=192.168.227.128:2888:3888 server.2=192.168.227.128:2889:3889 server.3=192.168.227.128:2890:3890
添加配置文件myid
vim /usr/local/zookeeper/conf/myid
1
/usr/local/zookeeper01/conf/zoo.cfg
vim /usr/local/zookeeper01/conf/zoo.cfg
dataDir=/usr/local/zookeeper01/dataDir dataLogDir=/usr/local/zookeeper01/dataLogDir clientPort=2182 server.1=192.168.227.128:2888:3888 server.2=192.168.227.128:2889:3889 server.3=192.168.227.128:2890:3890
添加配置文件myid
vim /usr/local/zookeeper/conf/myid
2
/usr/local/zookeeper02/conf/zoo.cfg
vim /usr/local/zookeeper02/conf/zoo.cfg
dataDir=/usr/local/zookeeper02/dataDir dataLogDir=/usr/local/zookeeper02/dataLogDir clientPort=2183 server.1=192.168.227.128:2888:3888 server.2=192.168.227.128:2889:3889 server.3=192.168.227.128:2890:3890
添加配置文件myid
vim /usr/local/zookeeper/conf/myid
3
节点创建配置完毕之后欧需要依次启动三个节点的zookeeper服务器
cd /usr/local/zookeeper01/bin
./zkServer.sh -server 192.168.227.128:2181 cd /usr/local/zookeeper01/bin ./zkServer.sh -server 192.168.227.128:2182 cd /usr/local/zookeeper01/bin ./zkServer.sh -server 192.168.227.128:2183
验证集群是否配置成功:
在一个zookeeper端口创建一个节点/team在另一个zookeeper端口查看是否存在这个节点/team,如果存在就代表配置成功
5-3 三台物理机(虚拟机)安装zookeeper
需要克隆三台虚拟机
将serveer的ip和端口替换即可 zoo.cfg都替换如下列属性dataDir=/usr/local/zookeeper/dataDir
dataLogDir=/usr/local/zookeeper/dataLogDir clientPort=2181 server.1=192.168.227.131:2888:3888 server.2=192.168.227.132:2888:3888 server.3=192.168.227.133:2888:3888
6-1 客户端与zk服务器的连接& zk会话重连机制
连不上
//zookeeper的地址public static final String zkAddress = "192.168.227.131:2181";public static void main(String[] args) throws IOException, InterruptedException, KeeperException { ZooKeeper zk = new ZooKeeper(zkAddress, 2000, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { System.out.println("watcher事件:" + watchedEvent.getState().toString()); } }); long sessionId = zk.getSessionId(); byte[] sessionPwd = zk.getSessionPasswd(); System.out.println("与zookeeper正在连接:" + zk.getState()); //连接过程需要时间 Thread.sleep(2000); System.out.println("与zookeepeer连接成功:" + zk.getState()); //zk会话重连 zk = new ZooKeeper(zkAddress, 2000, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { } }, sessionId, sessionPwd); System.out.println("与zookeeper正在连接:" + zk.getState()); Thread.sleep(2000); System.out.println("与zookeepeer重连成功:" + zk.getState());}//控制台打印与zookeeper正在连接:CONNECTINGwatcher事件:SyncConnected与zookeepeer连接成功:CONNECTEDwatcher事件:Closedzk状态:CLOSED与zookeepeer开始重连...与zookeeper正在连接:CONNECTING与zookeepeer重连成功:CONNECTED
如果连接不上zookeeper:请关闭虚拟机防火墙,再次连接
systemctl stop firewalld.service
6-2 创建节点
同步创建:zk.create(path, data, acl, CreateMode);
异步创建:zk.create(path, data, acl, CreateMode, CallBack, ctx);acl:控制权限策略
Ids.OPEN_ACL_UNSAFE–>world:anyone:crawd CREATOR_ALL_ACL–>auth:user:password:crawdCreateMode:节点类型:是一个枚举
PRESISTENT:持久节点 PRESISTENT_SEQUENTIAL:持久顺序节点 EPHEMERAL:临时节点 EPHEMERAL_SEQUENTIAL:临时顺序节点
//同步创建zk.create("/java", "java".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);//异步创建zk.create("/sys_java", "sys_java".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new MyCallBack(), ctx);//执行回调函数需要时间Thread.sleep(2000);
6-3 修改节点数据
同步方式
setData(path, data, version) 异步方式 setData(path, data, version, CallBack, ctx)6-4 删除节点
同步方式
delete(path, data, version) 异步方式 delete(path, data, version, CallBack, ctx)6-5 CountDownLatch的介绍
线程中的计数器
分布式锁中的计数器- 它是一个计数器,可以累减
- 多用于线程,乐意暂停也可以继续
- .await() .CountDown()
6-6 节点查询
//节点查询有同步查询有异步查询,在这里讨论的是同步查询,异步查询只不过有个回调函数,返回一些需要的数据,可以自己试试看//父节点查询ZooKeeperServer zooKeeperServer = new ZooKeeperServer(addressPath);//true表示再次添加watcher监听,false为不在添加byte[] data = zooKeeperServer.getZooKeeperServer().getData("/java", false, stat);String info = new String(data);System.out.print(info);//子节点查询ListnodeList = zookeeper.getZookeeperServer().getChildren("/java",false,stat);for(String nodeName : nodeList) { System.out.print(nodeName); }
发表评论
最新留言
关于作者
