一、zookeeper
-------------------------------------------------
1.管理大量主机的协同服务
2.是一个分布式应用,实现了分布式读写技术
3.提供的服务有:
名称服务 //按名称区分集群中的节点
配置管理, //对加入的节点进行最优化的处理
集群管理, //实时感知集群中节点的增减
领导推选服务, //leader和follower推选机制
锁与同步 //修改时锁定数据,实现容灾
高可靠数据注册机制 //节点宕机,数据仍然可用
二、ZK安装(单机版)
----------------------------------------------------------
1.下载zookeeper-3.4.9.tar.gz
2.tar开
3.创建符号连接
ln -s zookeeper-3.4.9 zk
4.配置环境变量
ZK_HOME="/soft/zk"
path=".....:/soft/zk/bin"
5.source一下
6.配置zk
a.[zk/conf/zoo.cfg]
$> cp zoo_sample.cfg zoo.cfg
-- 修改快照路径
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/ubuntu/zookeeper
7.启动zk服务
$>cd /soft/zk/bin
$>zkServer.sh start
8.查看端口,验证是否启动
$> netstat -ano | grep 2181
9.启动客户端,连接到服务器
$> zkCli.sh -server s100:2181
10.进入zk命令行,查看帮助
$[zk: s100:2181(CONNECTED) 1] help
三、使用zk
-----------------------------------------
1.创建节点以及节点关联的数据
[zk> create /a tom //在根节点下创建路径 /a 关联的数据是tom。
//而且不能跨节点创建,也就是父节点必须存在
//不关联数据也是不行的
2.查询节点
[zk> get /a //查看/a 节点关联的数据信息
3.更新节点数据
[zk> set /a tomse //更新节点关联的数据,并且版本+1
4.删除节点
[zk> delete /a //不能删除非空节点
[zk> rmr /a //递归删除,可以删除非空节点
四、通过API访问zk
-----------------------------------------------------
1.建立java项目,并添加maven依赖
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
public class TsZK {
public ZooKeeper zk = null;
@Before
public void getZk() throws Exception {
//连接串,可以是多个ip和端口组成的串
String conStr = "192.168.43.131:2181";
zk = new ZooKeeper(conStr, 5000, null);
}
/**
* 测试递归查询:列出所有节点
*/
@Test
public void tsLSR() throws Exception {
tsLS("/");
}
public void tsLS(String root) throws Exception {
//查询节点
List<String> list = zk.getChildren(root, null);
if (list !=null && list.size() > 0) {
for(String s : list)
{
if(root == "/") //说明是根
{
System.out.println(root +s);
tsLS(root +s);
}
else
{
System.out.println(root + "/" +s);
tsLS(root + "/" +s);
}
}
}
}
/**
* 测试创建节点
*/
@Test
public void tsCreateNode() throws Exception {
zk.create("/mynode", "mycreatenode".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
tsLSR();
}
/**
* 删除节点
*/
@Test
public void tsDelNode() throws Exception {
zk.delete("/mynode",0);
tsLSR();
}
/**
* 判断路径是否存在
*/
@Test
public void tsExists() throws Exception
{
Stat stat = zk.exists("/a/b", true);
if (stat == null) {
System.out.println("path not exits");
}
else
{
System.out.println("path exits" + stat.getNumChildren());
}
}
/**
* 查看节点数据
*/
@Test
public void tsGetNodeData() throws Exception
{
Watcher w = new Watcher() {
public void process(WatchedEvent event) {
System.out.println("data is changed");
}
};
byte [] bs = zk.getData("/a",w,null );
System.out.println(new String(bs));
}
/**
* 设定节点数据
*/
@Test
public void teSetNodeDate() throws Exception{
Stat stat = zk.exists("/a", true);
zk.setData("/a", "hao".getBytes(), stat.getVersion());
}
/**
* 测试监听机制
* 反复使用同一个观察者,实现反复监听
* 回调函数中添加注册机制,实现反复监听
*/
@Test
public void tsWatch() throws Exception {
final Stat stat = zk.exists("/a", true);
//反复使用同一个观察者,实现反复观察
Watcher w = new Watcher() {
public void process(WatchedEvent event) {
System.out.println("data id changed");
try {
zk.getData("/a", this, null);
} catch (Exception e) {
e.printStackTrace();
}
}
};
byte[] bs = zk.getData("/a", w, stat);
System.out.println(new String(bs));
while(true)
{
}
}
/**
* 测试监听机制
* 递归实现持续监听
*/
@Test
public void ts()
{
tsWatch_always();
while (true) {
}
}
public void tsWatch_always()
{
try{
final Stat stat = zk.exists("/a", true);
byte[] bs = zk.getData("/a", new Watcher() {
public void process(WatchedEvent event) {
System.out.println("data id changed");
tsWatch_always();
}
}, stat);
System.out.println("data = " + new String(bs));
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* 测试zk读
*/
public void tsRead()
{
}
}
五、ZK架构
-----------------------------------------------------
1.Client:
从server获取信息,并一定间隔向服务器发送心跳,证明alive.
连接服务器时,服务器会回传一个确认信息,如果没有得到响应,客户端就会尝试连接zk集群里的另外一台服务器
2.Server:
zk集群中的一员,向客户端提供所有服务,向客户端发送ack信息,表示自己alive
3.ensemble:
一组服务器,最小的节点数是3
4.leader:
服务器的一个节点,如果节点故障,自动恢复一个节点作为leader.
服务器启动的时候,会推选一个节点作为leader
5.follower:
作为leader的推选,而被推选为leader
六、ZNode
---------------------------------------------------------
1.znode是zk服务器中的节点(路径,kv对),由版本号,时间戳,访问控制列表,数据长度等组成
a.版本:数据变化版本递增,多客户端执行并发时尤其重要。
b.Acl:访问控制列表,权限控制,掌控所有节点的读写操作。类似于Linux的GUO
c.时间戳:毫秒数,从数据创建或者被修改至今的毫秒数值
d.DataLength:数据的字节数量,最大为1M
2.节点类型
a.Persistence znode 持久性节点
-- client退出也存在,默认节点选项
b.Ephemeral znode 临时性节点
-- client断开连接即删除,仅在客户端活跃时有效。
-- 不能有子节点。
-- leader推选的时候扮演重要角色
c.Sequential znode 序列性节点
-- 既可以是持久节点,也可以是临时节点。特点就是在你自定义的名字后面加上10个数字
-- 即使你创建相同名称的节点,也会不同。因为后面的10位数字是递增的
-- 在同步的时候很重要
七、Sessions 会话
-----------------------------------------------------------
1.FIFO:先进先出
2.一旦Client连接到Server,Session就建立了。
3.Client固定间隔向server发送心跳,以确定会话是有效的.超时的话,就认为客户端挂掉了
4.Cilent一旦被认为挂掉,就会删除临时节点
八、Watch 监视者
------------------------------------------------------------
1.被观察的节点上的数据一旦发生改变,就会通知观察者
2.客户端可以在read节点[zk.getData()]的时候,注册观察者。
3.观察模式只触发一次。
4.如果会话过期或者关闭,观察者也会被删除
九、zk工作流程
---------------------------------------------------------------
1.zk集群启动后,client会连接到集群中的其中的一个节点,这个节点可以是leader,也可以是follower
2.连通后,node会分配一个id给连接的client作为其标识。并发送ack身份确认信息给client
3.如果客户端没有收到ack,说明尝试连接的服务器有问题。那么客户端就会查找集群中的其他节点,继续请求连接,直到收到ack
4.client一旦连接成功,就会周期性的向server发送心跳信息,保证连接不会丢失
5.client读取数据:
client读取数据,发送读请求给连接的zknode,zknode读取自己的数据库,返回节点数据给client
6.client写入数据:
client存储数据,发送要写入的路径和数据(k,v)给连接的zknode,zknode会将kv数据转发给leader。
leader在补发给所有的follower。只有当大多数(超过半数)的节点响应成功,写操作才会成功。