zookeeper漫谈。
先解释是什么,再解释怎么用。
简介概述
其实学任何一项技术,首先都要弄明白,为什么需要这项技术。
日常开发工作中,单机应用开发是最简单的一种架构,即一台应用服务器,一台数据库服务器,就能够将一个单机应用成功运行起来。
假设网站运营很成功,当访问量达到一定程度的时候,单机应用就有了弊端。入口就这么大,一下子涌入一大堆人,不是人被挤坏了就是门被挤坏了,应用服务器和数据库服务器随时面临着崩溃。
摇摇欲坠的单机应用需要出现一个英雄来拯救它,这里我们先不引入高大上的名词,我们就事论事,如何解决入口太小但是用户太多的情况。
有以下两种解决方法,第一种是进行限流,即规定每天只允许5000用户访问;第二种是扩展门面,原来只能容纳5000的门面经过扩展可以达到10000了。
理论上来说对外开放的应用一般情况下都会选用第二种方案,毕竟好不容易获取到的流量却因为门面不够而去限流,这难免有点壮士断腕的感觉。但是在某种特殊情况下,短暂的限流也是一种剑走偏锋的解决方式。
接下来我们选用了方案二,即扩展门面的方式来解决该问题,反映在计算机世界里,就是将单机应用扩展为多台服务器同时协作提供服务的方式,毕竟人多力量大,机器多也力量大。
我们将原先的单机应用扩展为多台应用服务器,用户的服务请求会被分配至多台应用服务器中,即类比于导游知道目前哪个入口比较空闲,游客就会跟着导游的指引前往空闲的入口;多台数据库服务器,并进行了数据库的读写分离,效率大大提高,还将入口和出口进行了分离,用户访问我们的应用就觉得舒服多了。
在该场景中,导游就是我们本文的主角zookeeper,它最清楚入口的情况,并且每次增加入口都需要首先向它汇报,如果入口被填埋消失了也需要向它汇报,这样就保证导游所掌握的信息永远是最新的,能够引导用户到正确的入口。
至于zookeeper这个名字背后的含义,还是比较有意思。由于这个项目立项初期,已经有其他项目取了很多动物的名字,例如pig项目,而该项目主要是用来分布式环境的协调,那么就叫做动物园管理员吧,于是zookeeper就诞生了。
单机安装
Apache ZooKeeper? Releases
选择一个版本进行下载。
- 将下载的tar.gz压缩包传到服务器上,并进行解压
tar -xzvf apache-zookeeper-3.7.0-bin.tar.gz
mv apache-zookeeper-3.7.0-bin zookeeper-3.7.0
drwxr-xr-x 2 1000 1000 4096 Mar 17 17:45 bin
drwxr-xr-x 2 1000 1000 4096 Jul 27 14:06 conf
drwxr-xr-x 5 1000 1000 4096 Mar 17 17:45 docs
drwxr-xr-x 2 root root 4096 Jul 27 09:22 lib
-rw-r--r-- 1 1000 1000 11358 Mar 17 17:45 LICENSE.txt
drwxr-xr-x 2 root root 4096 Jul 27 10:41 logs
-rw-r--r-- 1 1000 1000 432 Mar 17 17:45 NOTICE.txt
-rw-r--r-- 1 1000 1000 2214 Mar 17 17:45 README.md
-rw-r--r-- 1 1000 1000 3570 Mar 17 17:45 README_packaging.md
找到conf目录中的zoo_sample.cfg文件,这是一个简单单机配置示例(集群配置详见下文)。重点只需要关注以下参数:
tickTime=2000
dataDir=/opt/zookeeper/data
dataLogDir=/opt/zookeeper/logs
clientPort=2181
进入到bin目录中,使用如下命令启动(启动zookeeper需要依赖服务器的java环境,需要注意配置好JAVA_HOME)
sh zkServer.sh start
sh zkServer.sh status
在控制台中打印出来Mode: standalone的字样,表示是单机模式的zookeeper已经部署成功了。
停止命令:
sh zkServer.sh stop
在bin目录下执行以下命令
sh zkCli.sh -server 127.0.0.1:2181
节点创建
留个坑:节点的概念?
create /data "myData"
get /data
ls /
get /data watch
set /data "test"
delete /data
集群部署
参考单机安装,我们已经学会了如何在一台服务器上安装zookeeper。而集群模式则是在单机的基础上,由多台服务器部署zookeeper,且互相之间能够被监听。
安装步骤都是一样的,无非就是体现在配置文件和各自的标识需要保证唯一。
首先我们在解压后的zookeeper目录下,新建两个文件夹,分别是data和logs。
在data目录下新建myid(无文件后缀名,文件全称就是myid)文件,内容只需要写数字,即1表示1号zookeeper,2表示2号zookeeper等。
配置文件中需要体现各自的访问ip地址,myid号等信息,例如:
#基本事件单元,以毫秒为单位,它用来指示心跳
tickTime=2000
#集群中的follower与leader之间 初始连接 时能容忍的最多心跳数(tickTime的数量)
initLimit=10
#集群中的follower与leader之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)
syncLimit=5
#存储内存中数据库快照的位置
dataDir=../data
#日志位置
dataLogDir=../log
#监听客户端连接的端口
clientPort=2181
#格式 server.id=host:port1:port2
#用来指出集群中的所有机器;有多少台机器,这里就要有多少条配置
#id就是机器的myid
#host就是机器的IP地址
#第一个端口是从 follower 连接到 leader的端口,
#第二个端口是用来进行 leader 选举的端口
server.1=host1:2888:3888
server.2=host2:2888:3888
server.3=host3:2888:3888
在三台服务器上都重复上述步骤,并各自启动成功之后,一个集群方式的zookeeper部署就完成了。
既然我们都学会了在不同的服务器上部署了集群zookeeper,伪集群模式还不是简简单单。
但是学习一种新的事物必须要先了解它为什么存在,即我们已经有了集群模式部署,为什么还要有伪集群模式?
我在一开始就考虑了这个问题,通过搜寻资料之后发现伪集群模式确实有它存在的道理。
集群模式是把多个zookeeper分别装在不同的服务器上,并通过myid标识和配置文件进行互相监听,从而实现集群部署,目的是为了将原先单机模式下一台服务器的性能得到扩展,通过扩充服务器数量使得单机故障影响降到最低并更好地提供服务。
而假设我的单机服务器性能足够优秀,一台更比六台强,那仅仅只是部署一个zookeeper就浪费了它的性能,这个时候我部署一个zookeeper集群也是完全没问题,但是由于是在一台服务器中实现的集群模式,所以称之为伪集群模式。
但是不建议在生产环境中使用,因为它无法避免单机故障,性能再好,也怕“菜刀”,你这台性能极好的服务器如果宕机了,那你整个集群就倒了,而集群模式则可以将故障率通过多台机器进行均摊从而降低整个集群宕机的可能性。
接下来介绍如何实现伪集群模式,由于是在一台服务器上实现,故需要特别注意端口不允许出现冲突的情况。
在同一个服务器下,解压三个zookeeper压缩包(详见安装步骤,重复三次)。文件夹命名为zookeeper-1、zookeeper-2、zookeeper-3。配置文件的区别在于clientPort参数的不同,并且需要注意myid文件,详情请见下文:
在zookeeper-1下新建一个data、logs目录,并且在data目录下新建一个myid文件,写入内容:1,表示这是一号zookeeper。同样进行配置文件的编写,进入到conf目录下编辑zoo.cfg
#基本事件单元,以毫秒为单位,它用来指示心跳
tickTime=2000
#集群中的follower与leader之间 初始连接 时能容忍的最多心跳数(tickTime的数量)
initLimit=10
#集群中的follower与leader之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)
syncLimit=5
#存储内存中数据库快照的位置
dataDir=../data
#日志位置
dataLogDir=../log
#监听客户端连接的端口
clientPort=12181
#格式 server.id=host:port1:port2
#用来指出集群中的所有机器;有多少台机器,这里就要有多少条配置
#id就是机器的myid
#host就是机器的IP地址
#第一个端口是从 follower 连接到 leader的端口,
#第二个端口是用来进行 leader 选举的端口
server.1=127.0.0.1:12888:13888
server.2=127.0.0.1:22888:23888
server.3=127.0.0.1:32888:33888
在zookeeper-2下新建一个data、logs目录,并且在data目录下新建一个myid文件,写入内容:2,表示这是二号zookeeper。同样进行配置文件的编写,进入到conf目录下编辑zoo.cfg
#基本事件单元,以毫秒为单位,它用来指示心跳
tickTime=2000
#集群中的follower与leader之间 初始连接 时能容忍的最多心跳数(tickTime的数量)
initLimit=10
#集群中的follower与leader之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)
syncLimit=5
#存储内存中数据库快照的位置
dataDir=../data
#日志位置
dataLogDir=../log
#监听客户端连接的端口
clientPort=22181
#格式 server.id=host:port1:port2
#用来指出集群中的所有机器;有多少台机器,这里就要有多少条配置
#id就是机器的myid
#host就是机器的IP地址
#第一个端口是从 follower 连接到 leader的端口,
#第二个端口是用来进行 leader 选举的端口
server.1=127.0.0.1:12888:13888
server.2=127.0.0.1:22888:23888
server.3=127.0.0.1:32888:33888
在zookeeper-3下新建一个data、logs目录,并且在data目录下新建一个myid文件,写入内容:3,表示这是三号zookeeper。同样进行配置文件的编写,进入到conf目录下编辑zoo.cfg
#基本事件单元,以毫秒为单位,它用来指示心跳
tickTime=2000
#集群中的follower与leader之间 初始连接 时能容忍的最多心跳数(tickTime的数量)
initLimit=10
#集群中的follower与leader之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)
syncLimit=5
#存储内存中数据库快照的位置
dataDir=../data
#日志位置
dataLogDir=../log
#监听客户端连接的端口
clientPort=32181
#格式 server.id=host:port1:port2
#用来指出集群中的所有机器;有多少台机器,这里就要有多少条配置
#id就是机器的myid
#host就是机器的IP地址
#第一个端口是从 follower 连接到 leader的端口,
#第二个端口是用来进行 leader 选举的端口
server.1=127.0.0.1:12888:13888
server.2=127.0.0.1:22888:23888
server.3=127.0.0.1:32888:33888
总结
目前只是简单了解了zookeeper的概念已经简单的部署方案,至于其中真正的应用、节点的意义、分布式锁等内容尚未接触,仍然需要进行深入了解后再带来进一步的分享。
参考资料:
|