Zookeeper学习
1.zookeeper概述
2.zookeeper操作
1.树形目录服务,和Unix的文件系统很类似,拥有层次化结构
2.每个节点被称为ZNode,保存 数据 和 节点信息
3.节点可以拥有子节点,同时允许少量数据存储(1MB)
4.节点可以分为四大类:
PERSISTENT 持久化节点
EPHEMERAL 临时节点
PERSISTENT_SEQUENTIAL 持久化顺序节点
EPHEMERAL_SEQUENTIAL 临时顺序节点
./zkServer.sh start/status/stop/restart
./zkCli.sh -server ip:端口(2181)
help
quit
ls /
ls /dubbo
create (-e/-s/-es) /name data
get /node
set /node data
delete /node
deleteall /node
ls -s /nodepath
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
1.建立连接 2.添加节点 3.删除节点 4.修改节点 5.查询节点 6.Watch事件监听 7.分布式锁的实现
3.==分布式锁==
1.客户端获取锁的时,在lock节点下创建**临时顺序**节点
2.然后获取lock下面的所有子节点,客户端获取所有的子节点之后,如果发现自己创建的子节点最小,则认为客户端获取到了锁,使用完之后,删除节点
3.如果发现自己创建的节点并非lock所有的子节点最小的,说明没有获取到锁,此时客户端需要找到比自己小的子节点,同时对其注册事件监听器,监听删除事件
4.如果发现比自己小的那个子节点被删除,则客户端的Watcher会收到相应的通知,此时在判断自己创建的节点是否为序号最小的,如果是,则获取锁,如果不是重复以上步骤。
InterProcessSemaphoreMutex
InterProcessMutex
InterProcessReadWriteLock
InterProcessMultiLock
InterProcessSemaphoreV2
private InterProcessMutex lock = new InterProcessMutex(client,"/lmy");
lock.acquire(1,TimeUnit.SECONDS);
lock.release();
4.集群
#介绍
#Leader选举:一个Leader多个follower
1.Serverid(服务器ID)编号越大,在算法中权重越大;
2.Zxid(数据ID)服务器中存放的最大数据ID值越大越新,权重越大
3.在Leader选举中,如果某台zk获得了超半数选票,则这个就成为Leader(顺序启动时,Leader为n/2+1位)
#搭建:
1.JDK环境和Zk压缩包
2.创建data目录,把conf下的zoo_sample.cfg改成zoo.cfg
3.配置集群:在每个data目录创建myid文件#echo 1 > ..../data/myid
4.修改配置文件,配置dataDir和clientPort和集群服务器列表
#server.1= 127.0.0.1:2881:3881 .....
#server.服务器ID=服务器IP:服务器通信端口:服务器间投票选举端口
5.启动各个zk服务 ./zkServer.sh start
#./zkServer.sh status 查看集群状态
#注意:集群多于半数宕机,整个集群会宕机;多于半数之后,其他节点也会复活
#zk集群角色:
1.leader角色: 处理事务请求和调度集群内部各个服务器
2.follower角色:处理非事务请求,转发事务请求给leader并参与leader选举投票
3.observer角色:处理客户端非事务请求,转发事务请求给leader
#zk集群多少台zk合适,台数多可靠性高但通信延时大
#经验:10个服务器: 3个; 20-->5;100-->11;200-->11
#=============配置文件详解==============
tickTime = 2000; #zk与客户端或其他服务端通信心跳时间,ms
initLimit =10; #Leader和Follower初始通信的最多心跳数
syncLimit = 5; #LF的同步时限,超过syncLimit*tickTime,认为follower宕机,移除它
dataDir: /tmp #zk的数据
clientPort=2181 #暴露的端口
5.算法问题
#zk怎么保证数据一致性 ZAB算法
1.Paxos算法:基于消息传递且具有高度容错的一致性算法(多个广播者或理解为leader)
2.ZAB算法:基于Paxos算法,但是只有一个leader
#CAP理论:一致性、可用性、分区容错性
1.zk保证的是CP即一致性和分区容错性。
2.进行leader选举时集群不可用。
ps:Curator代码demo
public class testZk {
private CuratorFramework client;
@Before
public void testConnect() {
CuratorFramework client1 = CuratorFrameworkFactory.newClient("127.0.0.1:2181", 3000, 3000
, new ExponentialBackoffRetry(3000, 10));
client1.start();
client = CuratorFrameworkFactory.builder().connectString("127.0.0.1:2181")
.sessionTimeoutMs(3000)
.connectionTimeoutMs(3000)
.retryPolicy(new ExponentialBackoffRetry(3000, 10))
.namespace("lmy")
.build();
client.start();
}
@Test
public void testCreate() throws Exception {
client.create().forPath("/lmy");
client.create().forPath("/lmy", "hhh".getBytes());
client.create().withMode(CreateMode.EPHEMERAL).forPath("/lmy");
client.create().creatingParentsIfNeeded().forPath("/lmy");
byte[] bytes = client.getData().forPath("/lmy");
System.out.println(new String(bytes));
List<String> childNodes = client.getChildren().forPath("/lmy");
List<String> cns = client.getChildren().forPath("/");
Stat status = new Stat();
byte[] info = client.getData().storingStatIn(status).forPath("/lmy");
System.out.println(status);
int version = status.getVersion();
client.setData().withVersion(version).forPath("/lmy", "hello".getBytes());
client.delete().forPath("/lmy");
client.delete().deletingChildrenIfNeeded().forPath("/lmy");
client.delete().guaranteed().forPath("/lmy");
client.delete().guaranteed().inBackground(new BackgroundCallback() {
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
System.out.println("删除成功后回调函数");
}
}).forPath("/lmy");
final NodeCache nodeCache = new NodeCache(client, "/lmy", true);
nodeCache.getListenable().addListener(new NodeCacheListener() {
public void nodeChanged() throws Exception {
System.out.println("节点变化了");
byte[] data = nodeCache.getCurrentData().getData();
System.out.println(new String(data));
}
});
nodeCache.getListenable().addListener(() -> System.out.println("节点变化了"));
nodeCache.start(true);
final PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/lmy", true);
pathChildrenCache.getListenable().addListener(
new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("子节点变化了");
System.out.println(event);
PathChildrenCacheEvent.Type type = event.getType();
if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
byte[] data = event.getData().getData();
System.out.println(new String(data));
}
}
}
);
pathChildrenCache.start();
TreeCache treeCache = new TreeCache(client,"/lmy");
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
System.out.println("节点变化了");
System.out.println(event);
}
});
}
@After
public void close() {
if (client != null) {
client.close();
}
}
}