2.创建临时顺序节点:在某个节点下创建节点,来一个请求则创建一个节点,由于是顺序的,所以序号最小的获得锁,当释放锁时,通知下一序号获得锁。
分布式队列队列方面,简单来说有两种:一种是常规的先进先出队列,另一种是等队列的队员聚齐以后才按照顺序执行。对于第一种的队列和上面讲的分布式锁服务中控制时序的场景基本原理一致,这里就不赘述了。
第二种队列其实是在 FIFO 队列的基础上作了一个增强。通常可以在 /queue 这个 Znode 下预先建立一个 /queue/num 节点,并且赋值为 n(或者直接给 /queue 赋值 n)表示队列大小。之后每次有队列成员加入后,就判断下是否已经到达队列大小,决定是否可以开始执行了。
这种用法的典型场景是:分布式环境中,一个大任务 Task A,需要在很多子任务完成(或条件就绪)情况下才能进行。这个时候,凡是其中一个子任务完成(就绪),那么就去 /taskList 下建立自己的临时时序节点(CreateMode.EPHEMERAL_SEQUENTIAL)。当 /taskList 发现自己下面的子节点满足指定个数,就可以进行下一步按序进行处理了。
使用 dokcer-compose 搭建集群上面我们介绍了关于 ZooKeeper 有这么多的应用场景,那么接下来就先学习如何搭建 ZooKeeper 集群然后再进行实战上面的应用场景。
文件的目录结构如下:
├── docker-compose.yml 编写 docker-compose.yml 文件docker-compose.yml 文件内容如下:
version: '3.4' services: zoo1: image: zookeeper restart: always hostname: zoo1 ports: - 2181:2181 environment: ZOO_MY_ID: 1 ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 zoo2: image: zookeeper restart: always hostname: zoo2 ports: - 2182:2181 environment: ZOO_MY_ID: 2 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181 zoo3: image: zookeeper restart: always hostname: zoo3 ports: - 2183:2181 environment: ZOO_MY_ID: 3 ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181在这个配置文件中,Docker 运行了 3 个 Zookeeper 镜像,通过 ports 字段分别将本地的 2181, 2182, 2183 端口绑定到对应容器的 2181 端口上。
ZOO_MY_ID 和 ZOO_SERVERS 是搭建 Zookeeper 集群需要的两个环境变量。ZOO_MY_ID 标识服务的 id,为 1-255 之间的整数,必须在集群中唯一。ZOO_SERVERS 是集群中的主机列表。
在 docker-compose.yml 所在目录下执行 docker-compose up,可以看到启动的日志。
连接 ZooKeeper将集群启动起来以后我们可以连接 ZooKeeper 对其进行节点的相关操作。
1.首先需要下载 ZooKeeper。
2.将其解压。
3.进入其 conf/ 目录,将 zoo_sample .cfg 改成 zoo.cfg。
配置文件说明 # The number of milliseconds of each tick # tickTime:CS通信心跳数 # Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位。 tickTime=2000 # The number of ticks that the initial # synchronization phase can take # initLimit:LF初始通信时限 # 集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)。 initLimit=5 # The number of ticks that can pass between # sending a request and getting an acknowledgement # syncLimit:LF同步通信时限 # 集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)。 syncLimit=2 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. # dataDir:数据文件目录 # Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里。 dataDir=http://www.likecs.com/data/soft/zookeeper-3.4.12/data # dataLogDir:日志文件目录 # Zookeeper保存日志文件的目录。 dataLogDir=http://www.likecs.com/data/soft/zookeeper-3.4.12/logs # the port at which the clients will connect # clientPort:客户端连接端口 # 客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。 clientPort=2181 # the maximum number of client connections. # increase this if you need to handle more clients #maxClientCnxns=60 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # #sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1 # 服务器名称与地址:集群信息(服务器编号,服务器地址,LF通信端口,选举端口) # 这个配置项的书写格式比较特殊,规则如下: # server.N=YYY:A:B # 其中N表示服务器编号,YYY表示服务器的IP地址,A为LF通信端口,表示该服务器与集群中的leader交换的信息的端口。B为选举端口,表示选举新leader时服务器间相互通信的端口(当leader挂掉时,其余服务器会相互通信,选择出新的leader)。一般来说,集群中每个服务器的A端口都是一样,每个服务器的B端口也是一样。但是当所采用的为伪集群时,IP地址都一样,只能时A端口和B端口不一样。