Zookeeper
1.zookeeper的介绍
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服 务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,[1] 提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在zookeeper-3.4.3\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
zookeeper服务结构图
zookeeper中 有一个leader该主机是用于写 写入的更新会自动同步到其他的 follower服务器中 如果leader挂掉后 会重新选举一个leader所以如果是集群环境 最少
要求有三台以上机器 如果leader挂掉 只剩一台机器 选举引发性能问题
2.zookeeper安装
下载zookeeper的网址:https://www.apache.org/dyn/closer.cgi/zookeeper/
将zookeeper中的zoo_sample.cfg复制改名为zoo.cfg然后进行配置
修改数据文件储存的目录:
在zookeeper的根目录下新建文件夹data
然后将zoo.cfg中的dataDir=指向data的路径(不陪不能双击运行zkServer.cmd)
(dataDir=D:\教学PPT\zookeeper\zookeeper-3.4.10\data)
参数说明:
参数
说明
tickTime
ZK中的一个时间单元。ZK中所有时间都是以这个时间单元为基础,进行整数倍配置的。例如,session的最小超时时间是2*tickTime。默认3000毫秒。这个单元时间不能设置过大或过小,过大会加大超时时间,也就加大了集群检测session失效时间;设置过小会导致session很容易超时,并且会导致网络通讯负载较重(心跳时间缩短)
initLimit
Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许Follower在initLimit时间内完成这个工作。通常情况下,我们不用太在意这个参数的设置。如果ZK集群的数据量确实很大了,Follower在启动的时候,从Leader上同步数据的时间也会相应变长,因此在这种情况下,有必要适当调大这个参数了。默认值为10,即10 * tickTime (No Java system property)
syncLimit
在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果Leader发出心跳包在syncLimit之后,还没有从Follower那里收到响应,那么就认为这个Follower已经不在线了。注意:不要把这个参数设置得过大,否则可能会掩盖一些问题,设置大小依赖与网络延迟和吞吐情况。默认为5,即5 * tickTime (No Java system property)
dataDir
就是把内存中的数据存储成快照文件snapshot的目录,同时myid也存储在这个目录下(myid中的内容为本机server服务的标识)。写快照不需要单独的磁盘,而且是使用后台线程进行异步写数据到磁盘,因此不会对内存数据有影响。默认情况下,事务日志也会存储在这里。建议同时配置参数dataLogDir,事务日志的写性能直接影响zk性能。
dataLogDir
日志文件存放目录
clientPort
客户端连接server的端口,即zk对外服务端口,一般设置为2181。
Zoo.cfg配置文件的解析
#心跳的时间间隔
tickTime=2000
#初始化同步数据花费的时间 10个tickTime
initLimit=10
#leader和follower之间互相发送心跳 检测对方 失效的时间间隔 5*tickTime
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
#数据文件的储存目录
dataDir=D:\教学PPT\zookeeper\zookeeper-3.4.10\data
# the port at which the clients will connect
#默认端口号
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.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#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
3.zookeeper原理图
4.zookeeper原理
Zookeeper是一个数据库是一个使用树形结构的数据库,可以用高可用的集群,机器分为两种角色leaderf,follower,leader负责写入follower负责分担读的压力,一个群集只有一个leader通过选择算法来实现,必须确保机器个数为2n+1集群中的所有机器都参与选举,票数最高的机器成为leader,leader写入的数据通过paxos算法,将所有数据同步
运行 bin/zkServer
连接zookeeper:
zkCli.cmd -server localhost:2181 输入help查看
zookeeper的存储方式:树结构包含多个znode每一个节点都可以有一个值和多个子节点
Zookeeper的三种zonde:
1.永久节点:数据被持久化 用户不调用删除 不会删除
2.临时节点:客户端连接时 白保留数据 客户端断开 数据被删除 注册中心master/slace
3.顺序节点:1-50000 抢票+分布式主键
常用的数据操作命令(树结构节点数据的操作)
ls / 显示根节点下所有的节点
[zk: localhost(CONNECTED) 1] ls /
[zookeeper]
create 在/ 下 新增一个sex节点 节点的值是 boy
[zk: localhost(CONNECTED) 2] create /sex boy
Created /sex
[zk: localhost(CONNECTED) 3] ls /
[sex, zookeeper]
获取/sex节点的值
[zk: localhost(CONNECTED) 5] get /sex
boy
cZxid = 0x2
ctime = Thu May 11 17:32:27 CST 2017
mZxid = 0x2
mtime = Thu May 11 17:32:27 CST 2017
pZxid = 0x2
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
重新设置sex节点的值
[zk: localhost(CONNECTED) 6] set /sex girl
cZxid = 0x2
ctime = Thu May 11 17:32:27 CST 2017
mZxid = 0x3
mtime = Thu May 11 17:33:16 CST 2017
pZxid = 0x2
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: localhost(CONNECTED) 7] get /sex
girl
cZxid = 0x2
ctime = Thu May 11 17:32:27 CST 2017
mZxid = 0x3
mtime = Thu May 11 17:33:16 CST 2017
pZxid = 0x2
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
删除节点
[zk: localhost(CONNECTED) 8] delete /sex
[zk: localhost(CONNECTED) 9] ls /
[zookeeper]
[zk: localhost(CONNECTED) 10]
其他
help 查看所有命令的帮助
close/quit 退出登录
connect ip:port 重新登录
histroy 查看操作历史记录 每个历史记录都有一个编号
redo 编号 重新执行history中编号对应的语句
close 关闭客户端连接
stat /sex 查看znode的/sex的状态信息
ls2 /sex 查看/sex所有的子节点 同时查看状态信息
rmr /sex 删除/sex以及他的所有子节点
setquota -n 1 /test 给/test节点设置允许的子节点个数是1个 添加子节点操作1个 给予警告 可以添加
-b 10 /test 给/test的值的长度限制为 10个字节
listquota /test 列出/test所有的配额
delquota -n /test 删除子节点设置的额配合
权限控制(ACL 【access control list】):
通过查看create 命令的语法 最后一个参数可以添加权限控制
权限包括 scheme:id:perm 三部分
scheme表示权限控制的方式 有通过ip【ip】和用户名密码(digest)两种方式
ID 表示具体授权允许的对象
ip模式:id就是允许访问该节点的ip
digest模式:就是允许访问的用户名和密码 格式为 :用户名:BASE64(SHA-1(用户名:密码))
perm 表示具体的权限
比如 读(READ) 写(WRITE) 创建(CRETE) 删除(DELETE) 管理员(ADMIN) 一般设置都是单词的第一个字母 比如 读是R 写是W
举例(假设存在两台zookeeper主机 192.168.58.131 ,192.168.58.132):
通过ip控制权限(131上添加了一个节点/sex 只允许132读 尝试在131上添加子节点出现错误 因为131是创建该节点的主机 允许delete删除该节点)
[zk: 192.168.58.131(CONNECTED) 19] create /sex boy ip:192.168.58.132:r
Created /sex
[zk: 192.168.58.131(CONNECTED) 20] create /sex/b 1
Authentication is not valid : /sex/b
加入依赖
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
Zookeeper的客户端
package cn.et;
import java.util.concurrent.TimeUnit;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
public class ZkTest {
public static void main(String[] args) throws InterruptedException {
//多台用,隔开
String zookeeperUrl="localhost:2181";
ZkClient zk=new ZkClient(zookeeperUrl,10000,50000);
//如果该节点不存在 执行创建
if(!zk.exists("/user")){
//创建一个永久节点/user
zk.createPersistent("/user");
//创建两个顺序节点/user/ls 返回顺序节点真是的名字
String znodeName=zk.create("/user/ls", "boy", CreateMode.PERSISTENT_SEQUENTIAL);
//创建一个临时节点/user/zs
zk.createEphemeral("/user/zs","girl");
}
zk.subscribeDataChanges("/db", new IZkDataListener(){
//db节点被删除时触发
public void handleDataChange(String path, Object arg1) throws Exception {
System.out.println(path);
}
//db节点数据被修改时触发
public void handleDataDeleted(String path) throws Exception {
System.out.println(path);
}
});
while(true){
TimeUnit.SECONDS.sleep(5);
}
}
}
public static void main(String[] args) {
String zookeeperUrl="localhost:2181";
ZkClient zk=new ZkClient(zookeeperUrl,10000,50000);
zk.writeData("/db", "my");
}
Zookeeper连接数据库
package cn.et;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer;
public class ZkConnection {
static Connection conn=null;
public static Connection getConn(String driverClass,String url,String userName,String password) throws Exception{
Class.forName(driverClass);
conn=DriverManager.getConnection(url,userName,password);
return conn;
}
public static void main(String[] args) throws Exception {
String zookeeperUrl="localhost:2181";
final ZkClient zk=new ZkClient(zookeeperUrl,10000,50000,new BytesPushThroughSerializer());
byte[] url=zk.readData("/db/url");
byte[] driverClass=zk.readData("/db/driverClass");
byte[] userName=zk.readData("/db/userName");
byte[] password=zk.readData("/db/password");
getConn(new String(driverClass),new String(url),new String(userName),new String(password));
System.out.println(conn);
zk.subscribeDataChanges("/db/url", new IZkDataListener() {
public void handleDataDeleted(String dataPath) throws Exception {
// TODO Auto-generated method stub
}
public void handleDataChange(String dataPath, Object data) throws Exception {
byte[] url=zk.readData("/db/url");
byte[] driverClass=zk.readData("/db/driverClass");
byte[] userName=zk.readData("/db/userName");
byte[] password=zk.readData("/db/password");
getConn(new String(driverClass),new String(url),new String(userName),new String(password));
}
});
}
}
web客户端的使用
可以使用web客户客户端exhibitor 下载地址(https://github.com/soabase/exhibitor)
可以使用jar包和war包的方式发布 安装过程参考 https://github.com/soabase/exhibitor/wiki/Building-Exhibitor
配置向导可以参考 https://github.com/soabase/exhibitor/wiki/Configuration-UI
eclipse插件更新地址:http://www.massedynamic.org/eclipse/updates/
可参考博客地址:http://blog.csdn.net/liaomin416100569/article/details/71642091