一、复习Flume
1、多个Agent之间数据传输尽可能选择avro-sink,avro-sources搭配,端口号要注意一样
2、sink-HDFS小文件
3、failover/load_balance
二、ZK
1、ZK使用场景
1)高可用:HDFS/HBase/Spark HA集群
2)API:
开发:Java/Scala操作ZK
Kafka:offset可以存储在ZK ==> 实时流处理:Kafka+Streaming 零数据丢失
2、分布式协调服务enables highly reliable distributed coordination
3、分布式系统:
NN native(挂掉) standby(起来),服务不终止或修改
4、ZK是一个管理各种大数据工具的集群
一般ZK需搭建的机器数:
n(n>1)/2+1 3/5/7....
5、一般使用的思路
ZK管理(Node REDIS/... )中的配置文件(configuration file same)一样
1:/ruozedata/conf/ruoze.conf
port=9999
2:watch
...download...
3:....
三、ZK部署
1、下载
http://archive.cloudera.com/cdh5/cdh/5/ 版本跟之前Hadoop的一样
2、解压
tar -zvxf zookeeper-3.4.5-cdh5.7.0.tar.gz -C /opt/app/
3、配置环境变量
export ZK_HOME=/opt/app/zookeeper-3.4.5-cdh5.7.0
export PATH=$ZK_HOME/bin:
4、复制配置文件
cp zoo_sample.cfg zoo.cfg
5、修改配置文件
dataDir=/opt/tmp/zookeeper
6、使用ZK
./zkServer.sh
7、启动
bin目录下:
./zkServer.sh start
8、查看状态
如果查看状态发现,zk NO RUN的话,先看一下bin目录下的zookeeper.out文件,查看报错信息。然后针对性的解决问题。
9、关闭
10、重启
./zkServer.sh restart
找不到进程号,说明没有启动。直接启动。
11、研究cfg文件配置的路径里面生成的version-2文件的用途
启动client
bin目录下:
./zkCli.sh
12、ZK客户端的端口号
13、version-2的内容
13、ZK命令概要
三、基本数据模式
1、一个树形结构
2、znode:跟UDF有点相似
临时节点
永久节点
特点:
znode:id ==> id>pid
znode data change ==> version + 1
data:not big
3、LS2 = ls + get
4、创建节点
create:
-e:临时节点
-s:顺序节点
create /ruoze ruozedata
创建的内容在第一行,数据长度为9
pZxid:最新修改的Zxid
cZxid: 是节点的创建时间所对应的Zxid格式时间戳。
mZxid:是节点的修改时间所对应的Zxid格式时间戳。
5、创建临时节点
create -e /ruoze/tmp ruoze-data
quit离开后临时节点消失
6、创建顺序节点,常用于分布式锁
7、不可创建连续节点
create /ruoze/a/b/c abc
可以使用curator实现
8、临时节点不可在下一层再创建节点
9、修改节点内容
set /ruoze new-data
set 和 delete 要注意version
10、ZK的乐观锁
修改节点内容并强行赋予version值
是不可再赋予为1.
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
11、ZK删除节点
delete /ruoze/seq0000000001
还可以跟版本删除
12、ZK四字命令
stat:
echo stat | nc localhost 2181
查节点情况:
dump:
echo dump | nc localhost 2181
查配置信息:
conf
echo conf |nc localhost 2181
四、ZK集群
主从节点
选举:
3个zk节点 一个master宕机后,会从其他两个节点里面选举出替代master的节点。
伪分布式:1台机器上搭建多个zk节点
1、复制多个zk应用,等同于多个节点
cp -r zookeeper-3.4.5-cdh5.7.0 zk001
cp -r zookeeper-3.4.5-cdh5.7.0 zk002
cp -r zookeeper-3.4.5-cdh5.7.0 zk003
2、进入zk001
修改conf.cfg
3、安装tree命令
1)yum install -y tree
报错镜像文件安装失败
2)下载源码编译
make
3)cp -af tree /usr/bin/
4)配置环境变量
4、tmp目录下创建zookeeper001、zookeeper002、zookeeper003且按顺序创建myid文件并输入1、2、3
touch myid
echo 1 >myid
5、删除原复制的文件zk002、zk003,重新复制一次
6、修改zk002、zk003的zoo.cfg文件中的端口
7、启动每个节点的服务
8、进入bin目录查看节点的状态
zk001
./zkServer.sh status
zk002
zk003
9、将其中一个节点客户端启动,并指定端口
./zkCli.sh -server localhost:2182
10、创建一个节点数据,并通过另外一个节点查看
从zk002进入
能获取节点1创建的数据,更新的数据也可以互相共享、同步
11、测试宕机的情形
上述发现zk002是leader
jps -m
kill -9 此进程
再查看节点状态,发现zk003是leader
连接zk002和端口
连接zk001和端口,可以获取数据
容错性很强!
五、真正的分布式
dataDir=/home/hadoop/app/tmp/zookeeper
server.1=ruoze-hadoop000:2888:3888
server.2=ruoze-hadoop001:2888:3888
server.3=ruoze-hadoop002:2888:3888
在tmp目录下
$(dataDir)/myid记得创建myid的文件并按一定顺序输入1
六、WATCH
1、针对每个节点的操作,都有一个监督者:watcher
2、zk里面的watcher是一次性的,除非使用API
3、监听创建/ruoze节点的动作
stat /ruoze watch
4、创建/ruoze节点
5、监听修改/ruoze节点内容变化的动作
get /ruoze watch
修改
set /ruoze dataisveryhard
再修改
这次就没有监听了,所以客户端是一次性的。
6、 监听的内容
NodeDeleted
NodeDataChanged
NodeCreated
七、ZK API
1、pom文件添加依赖
<zk.version>3.4.5-cdh5.7.0</zk.version>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zk.version}</version>
</dependency>
2、创建ZKConnectApp.java文件
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ZKConnectApp {
private static Logger logger = LoggerFactory.getLogger(ZKConnectApp.class);
public static void main(String[] args) {
ZooKeeper zk = new ZooKeeper()
}
查看Zookeeper类的参数:
3、连接ZK
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class ZKConnectApp {
private static Logger logger = LoggerFactory.getLogger(ZKConnectApp.class);
public static void main(String[] args) throws IOException, InterruptedException {
ZooKeeper zk = new ZooKeeper("hadoop002:2181",5000,null);
logger.warn("客户端开始连接ZK服务器...");
logger.warn("连接状态:{}",zk.getState());
Thread.sleep(2000);
logger.warn("连接状态:{}",zk.getState());
}
一定要传个watch()
4、查看watch类的内容
类似于scala的trait,要实现他需要 implement
5、implements一下
6、实现Watcher方法
先不重写
7、本来传null的watcher,现在new一个ZKConnetApp对象
ZooKeeper zk = new ZooKeeper("hadoop002:2181",5000,new ZKConnectApp());
现在不报错了
8、改造睡眠2S待连接的代码
CountDownLatch:数量往下减,初始值设置为1
connected.await();//代码挂起,等连接成功
配合监听的方法,等收到watch的通知就重新触发.await方法,代码顺利往下走,实现灵活挂起连接ZK。不需写死睡眠时间。
9、创建节点
查看源码
create方法里参数分别是
path:string
data:byte[]
acl:List,ZooDefs.Ids.OPEN_ACL_UNSAFE记住,ACL都用这个值
createMode(模式):即节点的类型:持久、临时,以及各自是否带顺序
String path = zk.create("/ruoze","ruozedata".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
logger.warn("创建节点:{}",path);
执行:
10、获取节点数据
getData()
由于getData是byte[]类型
所以getData要类型转换
没有对象,创建对象
执行:
toStrng方法默认返回当前对象(c)的内存地址,即hashCode
new String 返回的是真实的值
11、修改节点数据
//修改节点内容
zk.setData("/ruoze","ruoze_newdata".getBytes(),0);
最后的一个参数是版本号,要跟当前zk的版本号一致,但编程的过程中,可以传-1,就不需要每次查看版本号。或者每次修改之前,getversion
12、删除节点
//删除节点
zk.delete("/ruoze",-1);
源码:
package com.HBinz; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.sql.Connection; import java.util.concurrent.CountDownLatch; public class ZKConnectApp implements Watcher{ private static Logger logger = LoggerFactory.getLogger(ZKConnectApp.class); private static CountDownLatch connected = new CountDownLatch(1); public static void main(String[] args) throws IOException, InterruptedException, KeeperException { ZooKeeper zk = new ZooKeeper("hadoop002:2181",5000,new ZKConnectApp()); logger.warn("客户端开始连接ZK服务器..."); logger.warn("连接状态:{}", zk.getState()); connected.await(); logger.warn("连接状态:{}", zk.getState()); // String path = zk.create("/ruoze","ruozedata".getBytes(),ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); // logger.warn("创建节点:{}",path); org.apache.zookeeper.data.Stat stat = new org.apache.zookeeper.data.Stat(); // byte[] data = zk.getData("/ruoze",true,stat); // logger.warn("数据:{}",new String(data)); //修改节点内容 // zk.setData("/ruoze","ruoze_newdata2".getBytes(),-1); zk.delete("/ruoze",-1); } @Override public void process(WatchedEvent watchedEvent) { if (Event.KeeperState.SyncConnected == watchedEvent.getState()){ logger.warn("接收到watch的通知:",watchedEvent); connected.countDown(); } } }
13、获取节点的孩子数量
自己试试
八、常用的Java API操作ZK的客户端
zookeeper
zkclient:spark streaming + kafka
curator