赞
踩
用redis实现分布式锁比较复杂,使用zookeeper会比较简单。
官网
https://zookeeper.apache.org/
概览文档
https://zookeeper.apache.org/doc/current/zookeeperOver.html
ZooKeeper:分布式应用程序的分布式协调服务
zk集群
每个节点的数据都一样。有一个leader,其他都是follower,是一个主从集群。写操作只能发生在leader身上。
主挂了怎么办?zk可以快速自我修复。
下图左侧:可用状态
下图右侧:不可用状态(leader挂掉了)
不可用状态恢复到可用状态,应该越快越好!
官方压测:
存在错误中的可靠性表明部署如何响应各种故障。图中标记的事件如下:
1、追随者的失败和恢复
2、其他追随者的失败和恢复
3、领导者的失败
4、两个追随者的失败和恢复
5、另一个领导者的失败
官方压测结果:ZooKeeper只需不到200毫秒即可选出新的领导者。
不要把zk当数据库用
redis可以作为数据库使用,但zk不应该作为数据库。zk每个node只能存1M,是为了保证对外提供分布式协调时的速度。
临时节点
每个客户端连接到zk之后,一定会有一个session来代表这个客户端,用来表示当前的会话。
依托session,我们有了临时节点的概念,可以用来解决之前redis加锁时需要设置过期时间的问题:
客户端在,session就在,锁就在。
客户端不在了,session就不在了,锁就释放了。
序列节点
持久节点 和临时节点都可以作为序列节点。
一个小技巧:xshell可以同时向多个会话发送命令,在 查看->撰写栏
选中即可,先来看一下四个节点的ip:
四台虚拟机,装了 jdk1.8
最好不要用yum安装jdk,因为yum不是oracle的hotspotjvm,是openjdk。搞过大数据的都清楚,很多开源社区曾经的时候是openjdk hotspot都测试,后来它们只对oracle的测试,可能对openjdk不兼容
https://www.apache.org/dyn/closer.lua/zookeeper/zookeeper-3.6.1/apache-zookeeper-3.6.1-bin.tar.gz
注意大坑:在版本的更新记录中记载,从版本3.5.5开始,带有bin名称的包才是我们想要的下载可以直接使用的里面有编译后的二进制的包,而之前的普通的tar.gz的包里面是只是源码的包,无法直接使用!!
所以同学们,如果下载3.5.5以后的版本的Zookeeper安装包,我们乖乖的下载带有bin标识的包就不会有问题了
在node01上准备好安装包就好,另外三台后面我们直接拷贝
tar -xf apache-zookeeper-3.6.1-bin.tar.gz
先在node01配置好,然后将这个配置目录向node02,node03,node04分发就可以了。
mkdir /opt/mashibing mv apache-zookeeper-3.6.1-bin /opt/mashibing cd /opt/mashibing/apache-zookeeper-3.6.1-bin && cd conf cp zoo_sample.cfg zoo.cfg # zk 默认配置文件名称为zoo.cfg # 未来持久化数据的目录,里面创建 myid 文件,内容为1,代表配置文件里面对应的,这台机器的id号 mkdir -p /var/mashibing/zk && echo 1 > /var/mashibing/zk/myid && cat /var/mashibing/zk/myid cd /var/mashibing/zk vi zoo.cfg # 数据最好不要放在tmp目录下,所以我们将存放数据的目录修改成: dataDir=/var/mashibing/zk # 配置文件最后面添加: # 注意要提前配好IP地址与主机名映射的/etc/hosts文件,否则计算机怎么知道node01是谁?或者你不配的话,直接用ip地址代替nodexx也可以 server.1=node01:2888:3888 server.2=node02:2888:3888 server.3=node03:2888:3888 server.4=node04:2888:3888 # 含义:没有leader的时候,节点之间通过3888端口通信,投票选出leader之后,leader使用2888端口 # 如何快速选出leader?通过谦让,谁的id最大就用谁。过半通过即可(3台通过即可)。
关于IP地址与主机名映射的/etc/hosts文件配置:
https://blog.csdn.net/weixin_43716338/article/details/103572507
# 添加IP地址与主机名映射:
vi /etc/hosts
# 内容如下
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.131 node01
10.0.0.132 node02
10.0.0.133 node03
10.0.0.134 node04
四台机器配置相同
# 将当前目录下的mashibing拷贝到远程的与当前pwd相同的目录下,需要输入一下密码就ok # 以下三行全部在node01上操作 scp -r ./mashibing/ node02:`pwd` # node02 scp -r ./mashibing/ node03:`pwd` # node03 scp -r ./mashibing/ node04:`pwd` # node04 # 或者,如果你没有添加IP地址与主机名映射的话,直接使用ip地址拷贝也行 # 以下三行全部在node01上操作 # scp -r ./mashibing/ 10.0.0.132:/opt # node02 # scp -r ./mashibing/ 10.0.0.133:/opt # node03 # scp -r ./mashibing/ 10.0.0.134:/opt # node04 # 像node01那样,分别配置另外三个node的myid,并cat输出验证 mkdir -p /var/mashibing/zk && echo 2 > /var/mashibing/zk/myid && cat /var/mashibing/zk/myid # 在node02上操作 mkdir -p /var/mashibing/zk && echo 3 > /var/mashibing/zk/myid && cat /var/mashibing/zk/myid # 在node03上操作 mkdir -p /var/mashibing/zk && echo 4 > /var/mashibing/zk/myid && cat /var/mashibing/zk/myid # 在node04上操作
检查一下date
# 在 /etc/profile 最后面追加 ZOOKEEPER 的环境变量
vi /etc/profile
# 之前配的java environment
export JAVA_HOME=/usr/java/jdk1.8.0_251
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
#export PATH=$PATH:${JAVA_HOME}/bin
#zookeeper 注意CentOS7要加花括号,像下面这样
export ZOOKEEPER_HOME=/opt/mashibing/apache-zookeeper-3.6.1-bin
export PATH=$PATH:${JAVA_HOME}/bin:${ZOOKEEPER_HOME}/bin
# 重新加载配置文件
source /etc/profile
配置好之后,你在任何地方使用:
zk
+tab键
,就可以自动补全zk的指令了
同样的,把每个节点的环境变量远程同步一下
# 以下三行全部在node01上操作
scp -r /etc/profile node02:/etc # node02
scp -r /etc/profile node03:/etc # node03
scp -r /etc/profile node04:/etc # node04
然后在4台机器上都执行一下source /etc/profile
,让环境变量生效
zkServer.sh start-foreground
zkServer.sh status
查看当前机器上zk的状态(leader或者follower)
启动起来了,我们看到node01是leader,另外三台是follower
# 使用客户端连接,默认连接的是本机的zk
zkCli.sh
create
创建节点参数:create [-s] [-e] [-c] [-t ttl] path [data] [acl]
创建节点,-s表示顺序,-e表示临时,默认是持久节点,acl缺省表示不做任何权限限制
# 创建一个目录,我目前这个3.6.1版本可以不带着后面的双引号
create /test ""
# 向节点中存数据
# 注意每个节点最多只能放1M数据,而且zk和redis都是二进制安全的
set /test "hello world"
# 查看节点中的数据
get /test
zk的增删改写操作都是交给leader,leader单机维护一个单调递增的计数器,你会看到64字节的一个事务id:cZxid
,前面32位全是0的时候省略不写,用于标识leader的纪元。如果leader更新换代,新的leader会自动将事务id重新开始,并且修改事务id的前缀。
示例:create -e /ephemeraltest ephemeraltestdata
临时节点是和session绑定的,session也是实现了统一视图,是要消耗事务id的。
create /abc
“统一视图”不仅是针对节点,而且针对sessionid。每一个客户端连接进服务端之后,都会给它分配一个sessionid,而这个sessionid与临时节点是绑定的:session退出之后,临时节点也就不再保留了。那么问题来了,如果客户端连接的这个服务端挂了,那么客户端fail over重新连接到其他的服务端之后,之前创建的临时节点还存在吗?
答案是存在。因为“统一视图”不仅是针对节点,而且针对sessionid。
客户端连接进来之后,自动给它创建的sessionid:
这个sessionid也会消耗一个事务id、使事务id递增,由leader将这个sessionid同步到每一个节点上。
客户端断开的时候,也需要同步一下数据,所以也会消耗一个事务id。
示例create /student/age 会返回给你 Created /abc/age0000000001
使用create -s
,zk自动帮你保证节点之间的区分,可以让每一个客户端拿到的节点名称不会重复。
类似于分布式id,节点名称是全局唯一的。
你只需要拿到返回值,记住你自己的节点名称就可以了。
可以做隔离,统一命名。
任意两个节点之间,只要有一个(socket)连接,就可以实现双向通信。
node04
是leader
的情况为例使用 netstat -natp | egrep '(2888|3888)'
查看
今天就讲到这里,下节课我们讲Paxos~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。