zookeeper学习03 使用场景

zookeeper实际应用场景
zookeeper能够实现哪些场景
1)订阅发布/配置中心
watcher机制
统一配置管理(disconf)
实现配置信息的集中式原理和数据的动态更新
实现配置中心有俩种模式:push,pull
长轮询
zookeeper采用的是推拉相结合的方式。客户端向服务器端注册自己需要关注的节点。一旦节点数据发生变化,name服务器端会向客户端发送watcher事件通知。客户端收到通知后,主动到服务器端获取更新后的数据。
a 数据量比较小
b 数据内容在运行时发生动态变更
c 集群中的各个机器共享变量

2)分布式锁
2.1 redis setNX 存在则会返回0 不存在则返回数据
2.2 数据库 创建一个表 通过唯一索引的方式
create table(id,methodname..) methodname增加唯一索引
insert 一条数据 xxx delete 删除数据
mysql 有innodb来设置表锁或者行锁
2.3 zookeeper 有序节点
排他锁

共享锁(读锁)

3)负载均衡
请求/数据分摊多个计算单元
4)ID生成器
5)分布式队列
activeMQ kafka
a 先进先出队列
getchildren获取指定根节点下面的子节点
确定自己节点在子节点中的顺序
如果自己不是最小的子节点,监听比自己小的上一个子节点,否则处于等待 接受watcher通知,重复流程
b Barrier模式 =阻碍模式= 围栏模型 满足条件才会触发执行

6)统一命名服务
7)master选举
7*24小时可用 99.999%可用
master-slave模式
master出现故障 slave上位作为master 心跳机制去维持状态 脑裂

1)分布式锁实现

package com.lulf.DistrubuteLock.JavaApi;import java.io.IOException;
import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;public class ZookeeperClient {private final static String CONNECTSTRING = "192.168.48.133:2181,192.168.48.134:2181,"+ "192.168.48.135:2181,192.168.48.136:2181";private static int sessionTimeOut = 5000;//获取连接public static ZooKeeper getInstance() throws IOException, InterruptedException {final CountDownLatch countDownLatch = new CountDownLatch(1);ZooKeeper zooKeeper = new ZooKeeper(CONNECTSTRING, sessionTimeOut, new Watcher() {@Overridepublic void process(WatchedEvent paramWatchedEvent) {if (paramWatchedEvent.getState() == Event.KeeperState.SyncConnected) {countDownLatch.countDown();}}});countDownLatch.await();return zooKeeper;}public static int getSessionTimeOut() {return sessionTimeOut;}
}
复制代码
package com.lulf.DistrubuteLock.JavaApi;import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;public class DistributeLock {private static final String ROOT_LOCKS = "/LOCKS"; // 根节点private ZooKeeper zooKeeper;private int sessionTimeOut = 5000;// 会话超时时间private String lockID;// 记录锁节点IDprivate CountDownLatch countDownLatch = new CountDownLatch(1);private final static byte[] data = { 1, 2 };public DistributeLock() throws IOException, InterruptedException {this.zooKeeper = ZookeeperClient.getInstance();this.sessionTimeOut = ZookeeperClient.getSessionTimeOut();}// 获取锁的方法public boolean lock() {try {lockID = zooKeeper.create(ROOT_LOCKS + "/", data, ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);System.out.println(Thread.currentThread().getName() + "->成功创建lock节点[" + lockID + "]开始去竞争锁");List<String> childrenNodes = zooKeeper.getChildren(ROOT_LOCKS, true);// 排序从小到大SortedSet<String> sortedSet = new TreeSet<String>();for (String children : childrenNodes) {sortedSet.add(ROOT_LOCKS + "/" + children);}String first = sortedSet.first();// 拿到最小的节点if (lockID.equals(first)) {// 表示当前就是最小的System.out.println(Thread.currentThread().getName() + "success get lock,lock节点[" + lockID + "]");return true;}SortedSet<String> lessThanLockID = sortedSet.headSet(lockID);if (!lessThanLockID.isEmpty()) {String preLockId = lessThanLockID.last(); // 拿到比当前lockid这个节点更小的上一个节点zooKeeper.exists(preLockId, new LockWatcher(countDownLatch));countDownLatch.await(sessionTimeOut, TimeUnit.MILLISECONDS);// 上面这段代码意味着如果会话超时或者节点被删除System.out.println(Thread.currentThread().getName() + "成功获取锁,lock节点[" + lockID + "]");}return true;} catch (KeeperException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}return false;}// 释放锁的方法public boolean unlock() {System.out.println(Thread.currentThread().getName() + "-->开始释放锁:[" + lockID + "]");try {zooKeeper.delete(lockID, -1);System.out.println("节点[" + lockID + "]被成功删除");return true;} catch (Exception e) {e.getStackTrace().toString();}return false;}public static void main(String[] args) {CountDownLatch latch = new CountDownLatch(10);Random random = new Random();for (int i = 0; i < 10; i++) {new Thread(() -> {DistributeLock lock = null;try {lock = new DistributeLock();latch.countDown();latch.await();lock.lock();Thread.sleep(random.nextInt(500));} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}).start();}}
}
复制代码

运行程序

2)master选举 实现共享锁:

package com.lulf.DistrubuteLock.zkclient;import java.io.Serializable;public class UserCenter implements Serializable{/*** */private static final long serialVersionUID = -4060228979536051295L;private  int m_id;//机器信息private String mc_name; //机器名称public int getM_id() {return m_id;}public void setM_id(int m_id) {this.m_id = m_id;}public String getMc_name() {return mc_name;}public void setMc_name(String mc_name) {this.mc_name = mc_name;}
}
复制代码
package com.lulf.DistrubuteLock.zkclient;import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.exception.ZkNodeExistsException;/*** 选主服务* * @author lulf**/
public class MasterSelector {private ZkClient client;private final static String MASTER_PATH = "/master";// 需要争抢的节点private IZkDataListener dataListener;// 注册节点内容发生变化private UserCenter server; // 其他服务器private UserCenter master; // master节点private static boolean isrunning = false;ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);public MasterSelector(UserCenter server,ZkClient client) {this.server = server;this.client=client;this.dataListener = new IZkDataListener() {@Overridepublic void handleDataDeleted(String dataPath) throws Exception {// 节点如果被删除,发起一个选主操作chooseMaster();}@Overridepublic void handleDataChange(String dataPath, Object data) throws Exception {}};}public void start() {// 开始选举if(!isrunning){isrunning=true;client.subscribeDataChanges(MASTER_PATH, dataListener);//注冊节点时间chooseMaster();}}public void stop() {// 停止if(isrunning){isrunning=false;scheduledExecutorService.shutdown();client.unsubscribeDataChanges(MASTER_PATH, dataListener);//取消订阅releaseMaster();}}// 具体选主的服务private void chooseMaster() {if (!isrunning) {System.out.println("当前服务没有启动。。。");return;}try {client.createEphemeral(MASTER_PATH, server);master = server;// 把server节点赋值给masterSystem.out.println(master.getMc_name() + "-->我已经是master,开始领导你们");// 定时器// master释放锁,出现故障scheduledExecutorService.schedule(() -> {releaseMaster();}, 5, TimeUnit.SECONDS);//每5秒释放一次锁} catch (ZkNodeExistsException e) {e.getStackTrace().toString();//表示master已经存在UserCenter userCenter=client.readData(MASTER_PATH, true);if(userCenter==null){chooseMaster();//再次获取master}else{master=userCenter;}}}private void releaseMaster() {// 释放锁(故障模拟)//判断当前是否是master,只有master才需要释放锁if(checkMaster()){client.delete(MASTER_PATH, -1);//删除}}private boolean checkMaster() {// 判断当前的server是否是masterUserCenter userCenter=client.readData(MASTER_PATH);if(userCenter.getMc_name().equals(server.getMc_name())){master=userCenter;return true;}return false;}
}
复制代码
package com.lulf.DistrubuteLock.zkclient;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;public class MasterChooseDemo {private final static String CONNECTSTRING = "192.168.48.133:2181,192.168.48.134:2181,"+ "192.168.48.135:2181,192.168.48.136:2181";public static void main(String[] args) {List<MasterSelector>selectorList=new ArrayList<MasterSelector>();try {	for (int i = 0; i < 10; i++) {ZkClient zkClient=new ZkClient(CONNECTSTRING, 5000,5000,new SerializableSerializer());UserCenter userCenter=new UserCenter();userCenter.setM_id(i);userCenter.setMc_name("lulf_"+i);MasterSelector selector=new MasterSelector(userCenter,zkClient);selectorList.add(selector);selector.start();//触发选举操作TimeUnit.SECONDS.sleep(4);}	} catch (Exception e) {e.getStackTrace().toString();}finally {for (MasterSelector masterSelector : selectorList) {masterSelector.stop();}}}
}
复制代码

curator 提供应用场景封装

curator-reciples
提供了api调用
如:master/leader选举
分布式锁 读锁 写锁
分布式队列
。。。
LeaderLatch 阻塞
写一个master
LeaderSelector 自动抢
每个应用都写一个临时有序节点,根据最小的节点来获取优先点

package com.lulf.DistrubuteLock.curator;import java.util.concurrent.TimeUnit;import javax.swing.tree.ExpandVetoException;import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListener;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;
import org.apache.curator.framework.state.ConnectionState;
import org.apache.curator.retry.ExponentialBackoffRetry;public class MasterSelector {private final static String CONNECTSTRING = "192.168.48.133:2181,192.168.48.134:2181,"+ "192.168.48.135:2181,192.168.48.136:2181";private final static String MASTER_PATH="/curator_master_path";public static void main(String[] args) {CuratorFramework curatorFramework=CuratorFrameworkFactory.builder().connectString(CONNECTSTRING).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();LeaderSelector leaderSelector=new LeaderSelector(curatorFramework, MASTER_PATH, new LeaderSelectorListenerAdapter() {@Overridepublic void takeLeadership(CuratorFramework arg0) throws Exception {System.out.println("获取leader成功");TimeUnit.SECONDS.sleep(2);}});leaderSelector.autoRequeue();leaderSelector.start();//开始选举}
}
复制代码

zookeeper的集群角色
leader
leader是zookeeper集群的核心。
1 事务请求的唯一调度的矗立着,他需要保证事务处理的顺序性
2 集群内部各个服务器的调度者
follower
1 处理客户端非事务请求以及转发事务请求给leader服务器
2 参与事务请求提议的proposal投票 【客户端的一个事务请求需要半数服务投票通过才能通知leader commit,leader会发起一个提案,要求follower投票】
3 参与leader选举的投票
observer
1 观察zookeeper集群中最新状态的变化,并且把这些状态同步到observer服务器上。
2 增加observer不影响集群事务处理能力,同时能提升集群的非事务处理能力

zookeeper的集群组成
zookeeper一般是由2n+1台服务器组成

leader选举
1)leaderElection
2)AuthFastLeaderElection
3)FastLeaderElection

serverID :配置server集群的时候给定服务器的标识id myid
zxid:服务器它运行时产生的数据ID,zxid值越大,标识数据越新
Epoch:选举轮次 sid
server的状态:Looking,Following,Observering,Leading

第一次初始化启动的时候是Looking
1)所有集群中的server都会推荐自己为leader,然后把(myid,zxid,epoch)作为广播信息,广播给集群中的其他server,然后等待其他服务器返回。
2)每个服务器都会接受到来自集群中的其他服务器的投票,及群众的每个服务器在接受到投票之后,都会判断投票的有效性
a)判断逻辑时钟epoch 如果epoch大于自己当前的epoch,说明自己保存的epoch是过期,更新epoch,同事clear其他服务器送过来的选举数据,判断是否需要更新当前自己的选举情况
b)如果Epoch小于目前的epoch,说明对方的epoch过期,意味着对方服务器的选举轮次是过期的,只需要把自己的信息发送给对方
c)如果接收到的epoch等于当前的epoch,根据规则来判断是否有资格获得leader 接受到来自其他服务器的投票后,针对每一个投标,都需要将别人的投票和自己的投票进行pk
ZXID最大的服务器优先
3)统计投票

ZAB协议
拜占庭问题
paxos协议主要就是如何保证在分布式网络环境下,各个服务器如何达成一致最终保证数据的一致性问题。
ZAB协议,基于paxos协议的一个改进。

ZAB协议为分布式协调服务zookeeper专门设计的一种支持奔溃恢复的原子广播协议。
zookeeper并没有完全采用paxos算法,而是采用zab zookeeper stomic broadcast zab协议的原理:
1)在zookeeper的主备模式下,通过zab协议来保证集群中的各个副本数据的一致性
2)zookeeper是使用单一的主进程来接受并处理所有的事务请求,并采用zab协议,把数据的状态变更以事务请求的形式广播到其他节点
3)zab协议在主备模型架构中保证了同一时刻只能有一个主进程来广播服务器的状态变更
4)所有的事务请求必须由全局唯一的服务器来协调处理,这个服务器叫leader,其他叫follower
leader节点主要是负责把客户端的请求转化为一个事务提议(proposal),并且分发给集群中的所有follower节点,再等待所有follower节点反馈,一旦超过半数服务器进行了正确的反馈,nameleader就会commit这个消息。

奔溃恢复
原子广播

zab协议的工作原理
1)什么情况下zab协议会进入奔溃恢复模式
a 当服务器启动时
b 当leader服务器出现网络中断 奔溃 重启的情况
c 集群中已经不存在过半的服务器与该leader保持正常通行

2)zab协议进入奔溃恢复模式会做什么
a 当leader出现问题,zab协议进入奔溃恢复模式,并且选举出新的leader。当新的leader选举出来以后,如果集群中已经有过半机器完成了leader服务器的状态同步(数据同步),退出崩溃恢复。进入消息广播模式
b 当新的机器加入到集群中的时候,如果已经存在leader服务器,那么新加入的服务器就会自觉进入数据恢复模式,找到leader进行数据同步

问题:
假设一个事务在leader服务器被提交了,并且已经有过半的follower返回了ack。在leader节点把commit消息发送给follower机器之前,leader服务器挂了怎么办?
zab协议,一定需要保证已经被leader提交的事务也能够被所有follower提交。
zab协议需要协议,在奔溃恢复过程中跳过那些已经被丢弃的事务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php模板引擎循环start,PHP模板引擎Smarty内建函数section,sectionelse用法详解

本文实例讲述了PHP模板引擎Smarty内建函数section,sectionelse用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;section 是 Smarty 模板中除了 foreach 以外的另一种处理循环的方案&#xff0c;section 比 foreach 要灵活&#xff0c;就像是一个改进的 foreach 语句…

OpenHarmony操作系统与龙芯2K1000LA芯片完成适配,龙架构平台获得开源鸿蒙认证

近日&#xff0c;龙芯中科与软通动力控股公司鸿湖万联共同完成OpenHarmony操作系统与龙芯2K1000LA处理器的适配&#xff0c;“乘风1000”开发板&#xff08;搭载龙芯2K1000LA&#xff09;荣获OpenHarmony生态产品兼容性证书。至此&#xff0c;万物互联的OpenHarmony生态体系再次…

struts2开发action 的三种方法以及通配符、路径匹配原则、常量

struts2开发action 的三种方法 1、继承ActionSupport public class UserAction extends ActionSupport {// Action中业务处理方法public String login() {System.out.println("UserAction.login()"); // return "success";return SUCCESS;} } 2、实现…

闭包--闭包作用之保护(一)

闭包作用:保护 形成私有作用域,保护里面的私有变量不受外界干扰例如多人协作开发&#xff1a;A的代码有fn(),B的代码有fn(),但是他们不相互影响 // A的代码<script>(function() {function fn1() {console.log("aa")}window.fn1 fn1;})()// window.fn1() //11&…

left join 和 inner join

2019独角兽企业重金招聘Python工程师标准>>> left join 和 inner join 首先 MySQL 中 inner join 的效率确实要高于 left join。所以没必要使用 left join 转弯成 inner join 的效果。这样不但效率降低&#xff0c;可读性也会降低。 Number1 select from t1 left j…

oracle 数据库中拆分,oracle数据库字符串拆分

第一种 直接返回切分的字符串create or replace function Get_StrArrayLength(av_str varchar2,--要分割的字符串av_split varchar2 --分隔符号)return numberislv_str varchar2(1000);lv_length number;beginlv_str:ltrim(rtrim(av_str));lv_length:0;while instr(lv_str,av_s…

Vue3+.NET6,轻松开发管理后台!(可复用)

在GitHub是没找到简单好用的Vue3.NET6管理后台项目&#xff0c;有收藏的请评论区分享。这里分享一套Vue3 Axios TS Vite Element Plus .NET 6 WebAPI JWT SqlSugar的通用管理后台&#xff0c;前后端分离架构&#xff0c;各种最新框架组件&#xff0c;实现了管理后台几乎…

iOS网络请求安全认证(JWT,RSA)

在网络世界中&#xff0c;安全是一个很重要的问题&#xff0c;以往的HTTP请求已经不能承担这个安全任务&#xff0c;抓包工具一抓&#xff0c;你的所有网络请求全都曝光。当然&#xff0c;你可能会采用加密算法来加密数据&#xff0c;但是这仍然不够。 在移动端和服务器的通信过…

微信小程序黑客马拉松即将开始,来做最酷的 Mini Program Creators!

微信小程序黑客马拉松正式启动 近日&#xff0c;小程序斩获一项世界级殊荣——作为一项全新的技术和应用创新&#xff0c;小程序首次获选世界互联网领先科技成果。目前小程序应用数量已超过 100 万&#xff0c;覆盖了 200 多个细分行业&#xff0c;日活用户达到 2 亿。 微信小程…

oracle 文件写 n r,[oracle]log_archive_dest_n与DB_RECOVERY_FILE_DEST

DB_RECOVERY_FILE_DEST参数是默认的flashrecovery area的路径&#xff0c;里面存放有归档日志、闪回日志以及rman的备份文件等文件。LOG_ARCHIVE_DEST_n参数是存放归档日志的路径&#xff0c;n表示1~10的一个整数&#xff0c;由于归档日志在recovery的时候担当了重要的角色&…

记一次 .NET 某娱乐聊天流平台 CPU 爆高分析

一&#xff1a;背景 1.讲故事前段时间有位朋友加微信&#xff0c;说他的程序直接 CPU100%&#xff0c;每次只能手工介入重启&#xff0c;让我帮忙看下到底怎么回事&#xff0c;哈哈&#xff0c;这种CPU打满的事故&#xff0c;程序员压力会非常大, 我让朋友在 CPU 高的时候抓 2 …

linux下mariadb大小写敏感

2019独角兽企业重金招聘Python工程师标准>>> Linux下安装好mariadb后&#xff0c;在使用时会发现mariadb对大小写敏感&#xff0c;这对开发带来一定的不利&#xff0c;这时只要在配置文件中配置一下&#xff0c;取消大小写敏感即可&#xff1a; sudo vi /etc/MySQL/…

评论列表显示及排序,个人中心显示

1.显示所有评论{% for foo in ques.comments %} 2.所有评论排序uquestion db.relationship(Question, backrefdb.backref(comments, order_bycreat_time.desc)) 3.显示评论条数{{ ques.comments|length }} 1题代码如下&#xff1a; <h3>评论区:({{ ques.comments|length…

软件工程现行国标汇集

GB/T 8566-2007 《信息技术 软件生存周期过程》GB/T 8567-2006 《计算机软件文档编制规范》 GB/T 9385-2008《计算机软件需求规格说明规范》GB/T 9386-2008 《计算机软件测试文档编制规范》 GB/T 11457-2006《信息技术 软件工程术语》GB/T 14394-2008《计算机软件可靠性和可维护…

oracle listagg方法,Oracle实现字符串拼接和分离功能的方法(LISTAGG函数),oraclelistagg...

Oracle实现字符串拼接和分离功能的方法(LISTAGG函数)&#xff0c;oraclelistagg字符串拼接(String Aggregation Techniques)是数据处理时经常需要用到一个技术&#xff0c;比如需要按时间顺序拼装一个快递的运输记录&#xff0c;或者将流程中各个环节的处理人拼装为一个字符串。…

他俩都曾是技术大牛,创业这些年来有怎样的苦与乐?

这是头哥侃码的第263篇原创国庆假期回来&#xff0c;「头哥唠 B 唠」的直播仍在继续。这次我邀请了我工作上的老板和朋友&#xff0c;一起聊了聊关于 “技术创业路上的苦与乐”。熟悉他们两位的都知道&#xff0c;可以说是技术出身&#xff0c;然后创业当老板的代表。大家都知道…

maven,gradle本地缓存位置

gradle: 配置系统环境变量GRADLE_USER_HOME即可&#xff0c;值为缓存位置。 maven: 修改settings文件&#xff1a;maven的home路径下的conf文件夹下的settings.xml 对于有些IDEA&#xff0c;还需要配置。但是不要再打开项目后的FILE-->settings配置&#xff0c;而是需要在选…

git和php的区别,Git与Github的有什么区别

Git是一款免费&#xff0c;开源的分布是版本&#xff0c;用于敏捷高效的处理任何或小或大的项目。分布式相对于集中式的最大区别在于开发者可以提到本地&#xff0c;每个开发者通过克隆&#xff0c;在本地磁盘内拷贝一个完整的GIt仓库。Git的功能特性&#xff1a;1.从服务器上克…

E20171214-sl

well-grounded  地基打的好 relevent adj. 有关的&#xff0c;中肯的; 相关联的proposal n. 建议; 提议; 求婚; 〈美〉投标;转载于:https://www.cnblogs.com/lancgg/p/8281675.html

客户端嵌套 Web 页面如何选择

客户端嵌套 Web 页面如何选择客户端嵌套 Web 页面如何选择作者&#xff1a;驚鏵在使用客户端嵌套WEB页面有一下几种方案&#xff1a;WebView2[1]Electron[2]NW.js[3]sciter[4]miniblink[5]现在国内众多桌面程序都是用了以下五种&#xff0c;因为它跨平台更为方便&#x1f447;。…