回顾Redis

用redis实现分布式锁比较复杂,使用zookeeper会比较简单。
在这里插入图片描述


一、ZooKeeper介绍

官网
https://zookeeper.apache.org/

概览文档
https://zookeeper.apache.org/doc/current/zookeeperOver.html

1、什么是ZooKeeper?

ZooKeeper:分布式应用程序的分布式协调服务

  • ZooKeeper使用了按照文件系统熟悉的目录树结构命名的数据模型
  • ZooKeeper提供的名称空间与标准文件系统的名称空间非常相似。名称是由斜杠(/)分隔的一系列路径元素。ZooKeeper命名空间中的每个节点都由路径标识
  • 名称空间由数据寄存器(称为znode)组成,它们类似于文件和目录。与设计用于存储的典型文件系统不同,ZooKeeper数据保留在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟数。
  • 像它协调的分布式进程一样,ZooKeeper本身也可以在称为集合的一组主机上进行复制
  • 众所周知,协调服务很难做到。它们特别容易出现诸如比赛条件和死锁之类的错误。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就不在了,锁就释放了。

序列节点
持久节点 和临时节点都可以作为序列节点。

在这里插入图片描述

2、ZooKeeper 的特点

  • 顺序一致性:来自客户端的更新将按照发送的顺序应用。
  • 原子性:数据更新的成功或失败,要么全部节点都成功,要么全部节点都失败(最终一致性)
  • 统一视图:无论客户端连接到哪个服务器,客户端都将看到相同的服务视图。即使客户端故障转移到具有相同会话的其他服务器,客户端也永远不会看到系统的较旧视图。
  • 可靠性:一旦应用了更新,该更新将一直持续到客户端覆盖更新为止。
  • 及时性:确保系统的客户视图在特定时间范围内是最新的(很短的时间内内达成最终一致性)。

二、ZooKeeper 安装

一个小技巧:xshell可以同时向多个会话发送命令,在 查看->撰写栏 选中即可,先来看一下四个节点的ip:
在这里插入图片描述

1、准备

四台虚拟机,装了 jdk1.8
最好不要用yum安装jdk,因为yum不是oracle的hotspotjvm,是openjdk。搞过大数据的都清楚,很多开源社区曾经的时候是openjdk hotspot都测试,后来它们只对oracle的测试,可能对openjdk不兼容
在这里插入图片描述

2、下载好ZK的tar压缩包

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上准备好安装包就好,另外三台后面我们直接拷贝

3、tar xf 解压

tar -xf apache-zookeeper-3.6.1-bin.tar.gz

4、创建目录

先在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台通过即可)。

5、准备远程拷贝目录

关于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

四台机器配置相同
在这里插入图片描述

6、添加完成之后,可以开始远程拷贝到另外三个节点上了

# 将当前目录下的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上操作

在这里插入图片描述

7、检查四台机器的时间是否一致

检查一下date
在这里插入图片描述

8、配置ZK的环境变量

# 在 /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,让环境变量生效

9、启动ZK

zkServer.sh start-foreground

zkServer.sh status查看当前机器上zk的状态(leader或者follower)

在这里插入图片描述
启动起来了,我们看到node01是leader,另外三台是follower
在这里插入图片描述

10、使用客户端连接

# 使用客户端连接,默认连接的是本机的zk
zkCli.sh

(1) 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的前缀。
在这里插入图片描述

(2)创建临时节点 示例:create -e /ephemeraltest ephemeraltestdata

临时节点是和session绑定的,session也是实现了统一视图,是要消耗事务id的。

create /abc
“统一视图”不仅是针对节点,而且针对sessionid。每一个客户端连接进服务端之后,都会给它分配一个sessionid,而这个sessionid与临时节点是绑定的:session退出之后,临时节点也就不再保留了。那么问题来了,如果客户端连接的这个服务端挂了,那么客户端fail over重新连接到其他的服务端之后,之前创建的临时节点还存在吗?
答案是存在。因为“统一视图”不仅是针对节点,而且针对sessionid。

客户端连接进来之后,自动给它创建的sessionid:
在这里插入图片描述
这个sessionid也会消耗一个事务id、使事务id递增,由leader将这个sessionid同步到每一个节点上。
客户端断开的时候,也需要同步一下数据,所以也会消耗一个事务id。

(3)创建顺序节点 示例create /student/age 会返回给你 Created /abc/age0000000001

使用create -s,zk自动帮你保证节点之间的区分,可以让每一个客户端拿到的节点名称不会重复
类似于分布式id,节点名称是全局唯一的。
你只需要拿到返回值,记住你自己的节点名称就可以了。
可以做隔离,统一命名。
在这里插入图片描述


附:简版简单笔记

在这里插入图片描述


节点间通信原理

任意两个节点之间,只要有一个(socket)连接,就可以实现双向通信
在这里插入图片描述

node04leader的情况为例

在这里插入图片描述

节点间连接情况如下

使用 netstat -natp | egrep '(2888|3888)' 查看
在这里插入图片描述

今天就讲到这里,下节课我们讲Paxos~

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐