Zookeeper实现分布式锁、Zookeeper实现配置中心

一、Zookeeper实现分布式锁

分布式锁主要用于在分布式环境中保证数据的一致性。

包括跨进程、跨机器、跨网络导致共享资源不一致的问题。

1.Zookeeper分布式锁的代码实现 

 新建一个maven项目ZK-Demo,然后在pom.xml里面引入相关的依赖

 <dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.10</version></dependency>

2. Zookeeper分布式锁的核心代码实现

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/**
* 
* @Description: Zookeeper分布式锁的核心代码实现
* @author leeSmall
* @date 2018年9月4日
*
*/
public class DistributedLock implements Lock {private static Logger logger = LoggerFactory.getLogger(DistributedLock.class);private static final String ZOOKEEPER_IP_PORT = "192.168.152.130:2181";private static final String LOCK_PATH = "/LOCK";private ZkClient client = new ZkClient(ZOOKEEPER_IP_PORT, 4000, 4000, new SerializableSerializer());private CountDownLatch cdl;private String beforePath;// 当前请求的节点前一个节点private String currentPath;// 当前请求的节点// 判断有没有LOCK目录,没有则创建public DistributedLock() {if (!this.client.exists(LOCK_PATH)) {this.client.createPersistent(LOCK_PATH);}}public void lock() {//尝试去获取分布式锁失败if (!tryLock()) {//对次小节点进行监听waitForLock();lock();} else {logger.info(Thread.currentThread().getName() + " 获得分布式锁!");}}public boolean tryLock() {// 如果currentPath为空则为第一次尝试加锁,第一次加锁赋值currentPathif (currentPath == null || currentPath.length() <= 0) {// 创建一个临时顺序节点currentPath = this.client.createEphemeralSequential(LOCK_PATH + '/', "lock");System.out.println("---------------------------->" + currentPath);}// 获取所有临时节点并排序,临时节点名称为自增长的字符串如:0000000400List<String> childrens = this.client.getChildren(LOCK_PATH);//由小到大排序所有子节点Collections.sort(childrens);//判断创建的子节点/LOCK/Node-n是否最小,即currentPath,如果当前节点等于childrens中的最小的一个就占用锁if (currentPath.equals(LOCK_PATH + '/' + childrens.get(0))) {return true;} //找出比创建的临时顺序节子节点/LOCK/Node-n次小的节点,并赋值给beforePathelse {int wz = Collections.binarySearch(childrens, currentPath.substring(6));beforePath = LOCK_PATH + '/' + childrens.get(wz - 1);}return false;}//等待锁,对次小节点进行监听private void waitForLock() {IZkDataListener listener = new IZkDataListener() {public void handleDataDeleted(String dataPath) throws Exception {logger.info(Thread.currentThread().getName() + ":捕获到DataDelete事件!---------------------------");if (cdl != null) {cdl.countDown();}}public void handleDataChange(String dataPath, Object data) throws Exception {}};// 对次小节点进行监听,即beforePath-给排在前面的的节点增加数据删除的watcherthis.client.subscribeDataChanges(beforePath, listener);if (this.client.exists(beforePath)) {cdl = new CountDownLatch(1);try {cdl.await();} catch (InterruptedException e) {e.printStackTrace();}}this.client.unsubscribeDataChanges(beforePath, listener);}//完成业务逻辑以后释放锁public void unlock() {// 删除当前临时节点client.delete(currentPath);}// ==========================================public void lockInterruptibly() throws InterruptedException {}public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return false;}public Condition newCondition() {return null;}
}3.2 在业务里面使用分布式锁
package com.study.demo.lock;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/**
* 
* @Description: 在业务里面使用分布式锁
* @author leeSmall
* @date 2018年9月4日
*
*/
public class OrderServiceImpl implements Runnable {private static OrderCodeGenerator ong = new OrderCodeGenerator();private Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);// 同时并发的线程数private static final int NUM = 10;// 按照线程数初始化倒计数器,倒计数器private static CountDownLatch cdl = new CountDownLatch(NUM);private Lock lock = new DistributedLock();// 创建订单接口public void createOrder() {String orderCode = null;//准备获取锁lock.lock();try {// 获取订单编号orderCode = ong.getOrderCode();} catch (Exception e) {// TODO: handle exception} finally {//完成业务逻辑以后释放锁lock.unlock();}// ……业务代码logger.info("insert into DB使用id:=======================>" + orderCode);}public void run() {try {// 等待其他线程初始化cdl.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 创建订单createOrder();}public static void main(String[] args) {for (int i = 1; i <= NUM; i++) {// 按照线程数迭代实例化线程new Thread(new OrderServiceImpl()).start();// 创建一个线程,倒计数器减1cdl.countDown();}}
}

 工具类:

import java.text.SimpleDateFormat;
import java.util.Date;public class OrderCodeGenerator {// 自增长序列private static int i = 0;// 按照“年-月-日-小时-分钟-秒-自增长序列”的规则生成订单编号public String getOrderCode() {Date now = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");return sdf.format(now) + ++i;}}
二.新建一个zookeeper配置中心类,从zookeeper动态获取数据库配置
import java.util.List;
import java.util.Properties;import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;import com.zaxxer.hikari.HikariDataSource;/**
* 
* @Description: zookeeper配置中心类,从zookeeper动态获取数据库配置
* @author leeSmall
* @date 2018年9月10日
*
*/
public class ZookeeperConfigurerCentral {//curator客户端private CuratorFramework zkClient;//curator事件监听private TreeCache treeCache;//zookeeper的ip和端口private String zkServers;//zookeeper上的/Jdbc路径private String zkPath;//超时设置private int sessionTimeout;//读取zookeeper上的数据库配置文件放到这里private Properties props;public ZookeeperConfigurerCentral(String zkServers, String zkPath, int sessionTimeout) {this.zkServers = zkServers;this.zkPath = zkPath;this.sessionTimeout = sessionTimeout;this.props = new Properties();//初始化curator客户端initZkClient();//从zookeeper的Jdbc节点下获取数据库配置存入propsgetConfigData();//对zookeeper上的数据库配置文件所在节点进行监听,如果有改变就动态刷新propsaddZkListener();}//初始化curator客户端private void initZkClient() {zkClient = CuratorFrameworkFactory.builder().connectString(zkServers).sessionTimeoutMs(sessionTimeout).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();zkClient.start();}//从zookeeper的Jdbc节点下获取数据库配置存入propsprivate void getConfigData() {try {List<String> list = zkClient.getChildren().forPath(zkPath);for (String key : list) {String value = new String(zkClient.getData().forPath(zkPath + "/" + key));if (value != null && value.length() > 0) {props.put(key, value);}}} catch (Exception e) {e.printStackTrace();}}//对zookeeper上的数据库配置文件所在节点进行监听,如果有改变就动态刷新propsprivate void addZkListener() {TreeCacheListener listener = new TreeCacheListener() {public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {if (event.getType() == TreeCacheEvent.Type.NODE_UPDATED) {getConfigData();WebApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext();HikariDataSource dataSource = (HikariDataSource) ctx.getBean("dataSource");System.out.println("================"+props.getProperty("url"));dataSource.setJdbcUrl(props.getProperty("url"));dataSource.setUsername(props.getProperty("uname"));dataSource.setPassword(props.getProperty("password "));dataSource.setDriverClassName(props.getProperty("driver "));}}};treeCache = new TreeCache(zkClient, zkPath);try {treeCache.start();treeCache.getListenable().addListener(listener);} catch (Exception e) {e.printStackTrace();}}public Properties getProps() {return props;}public void setZkServers(String zkServers) {this.zkServers = zkServers;}public void setZkPath(String zkPath) {this.zkPath = zkPath;}public void setSessionTimeout(int sessionTimeout) {this.sessionTimeout = sessionTimeout;}
}

 新建一个加载props里面的数据库配置的类

import java.util.Properties;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;/**
* 
* @Description: 加载props里面的数据库配置,这个类等价于以前在xml文件里面的配置:
* <context:property-placeholder location="classpath:config/jdbc_conf.properties"/>
* @author leeSmall
* @date 2018年9月10日
*
*/
public class ZookeeperPlaceholderConfigurer extends PropertyPlaceholderConfigurer {private ZookeeperConfigurerCentral zkConfigurerCentral;@Overrideprotected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)throws BeansException {System.out.println(zkConfigurerCentral.getProps());super.processProperties(beanFactoryToProcess, zkConfigurerCentral.getProps());}public void setzkConfigurerCentral(ZookeeperConfigurerCentral zkConfigurerCentral) {this.zkConfigurerCentral = zkConfigurerCentral;}
}

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

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

相关文章

大数据面试SQL题-笔记02【查询、连接、聚合函数】

大数据面试SQL题复习思路一网打尽&#xff01;(文档见评论区)_哔哩哔哩_bilibiliHive SQL 大厂必考常用窗口函数及相关面试题 大数据面试SQL题-笔记01【运算符、条件查询、语法顺序、表连接】大数据面试SQL题-笔记02【查询、连接、聚合函数】​​​​​​​ 目录 01、查询 01…

Unity类银河战士恶魔城学习总结(P145 Save Skill Tree 保存技能树)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了技能树的保存 警告&#xff01;&#xff01;&#xff01; 如果有LoadData&#xff08;&#xff09;和SaveData(&#xff09;…

redmi 12c 刷机

刷机历程 一个多月前网购了redmi 12c这款手机, 价格只有550,用来搞机再适合不过了, 拆快递后就开始倒腾,网上有人说需要等7天才能解锁,我绑定了账号过了几天又忍不住倒腾,最后发现这块手机不用等7天解锁成功了,开始我为了获取root权限, 刷入了很火的magisk,但是某一天仍然发现/…

YOLO系列论文综述(从YOLOv1到YOLOv11)【第1篇:概述物体检测算法发展史、YOLO应用领域、评价指标和NMS】

目录 1 前言2 YOLO在不同领域的应用3 物体检测指标和NMS3.1 mAP和IOU3.2 mAP计算流程3.2.1 VOC 数据集3.2.2 微软 COCO 数据集 3.3 NMS 1 前言 最近在做目标检测模型相关的优化&#xff0c;重新看了一些新的论文&#xff0c;发现了几篇写得比较好的YOLO系列论文综述&#xff0…

【通俗理解】步长和学习率在神经网络中是一回事吗?

【通俗理解】步长和学习率在神经网络中是一回事吗&#xff1f; 【核心结论】 步长&#xff08;Step Size&#xff09;和学习率&#xff08;Learning Rate, LR&#xff09;在神经网络中并不是同一个概念&#xff0c;但它们都关乎模型训练过程中的参数更新。 【通俗解释&#x…

STL之算法概览

目录 算法概览 算法分析与复杂度标识O() STL算法总览 质变算法mutating algorithms----会改变操作对象之值 非质变算法nonmutating algorithms----不改变操作对象之值 STL算法的一般形式 算法的泛化过程 算法概览 算法&#xff0c;问题之解法也。 以有限的步骤&#xff0…

华为IPD流程管理体系L1至L5最佳实践-解读

该文档主要介绍了华为IPD流程管理体系&#xff0c;包括流程体系架构、流程框架实施方法、各业务流程框架示例以及相关案例等内容&#xff0c;旨在帮助企业建立高效、规范的流程管理体系&#xff0c;实现业务的持续优化和发展。具体内容如下&#xff1a; 1. 华为流程体系概述 -…

【青牛科技】 D2822M 双通道音频功率放大电路芯片介绍,用于便携式录音机和收音机作音频功率放大器

概述&#xff1a; D2822M 用于便携式录音机和收音机作音频功率放大器。D2822M 采用 DIP8 和 SOP8 封装形式。 特点&#xff1a;  电源电压降到 1.8V 时仍能正常工作  交越失真小  静态电流小  可作桥式或立体声式功放应用  外围元件少  通道分离度高  开机和关机…

【Python中while循环】

一、深拷贝、浅拷贝 1、需求 1&#xff09;拷贝原列表产生一个新列表 2&#xff09;想让两个列表完全独立开&#xff08;针对改操作&#xff0c;读的操作不改变&#xff09; 要满足上述的条件&#xff0c;只能使用深拷贝 2、如何拷贝列表 1&#xff09;直接赋值 # 定义一个…

抖音短视频矩阵源代码部署搭建流程

抖音短视频矩阵源代码部署搭建流程 1. 硬件准备 需确保具备一台性能足够的服务器或云主机。这些硬件设施应当拥有充足的计算和存储能力&#xff0c;以便支持抖音短视频矩阵系统的稳定运行。 2. 操作系统安装 在选定的服务器或云主机上安装适合的操作系统是关键步骤之一。推…

kmeans 最佳聚类个数 | 轮廓系数(越大越好)

轮廓系数越大&#xff0c;表示簇内实例之间紧凑&#xff0c;簇间距离大&#xff0c;这正是聚类的标准概念。 簇内的样本应该尽可能相似。不同簇之间应该尽可能不相似。 目的&#xff1a;鸢尾花数据进行kmeans聚类&#xff0c;最佳聚类个数是多少&#xff1f; plot(iris[,1:4…

day04 企业级Linux安装及远程连接知识实践

1. 使用传统的网卡命名方式 在启动虚拟机时&#xff0c;按tab键进入编辑模式 添加命令&#xff1a; net.ifnames0 biosdevname0 这样linux系统会使用传统的网卡命名&#xff0c;例如eth0、eth1…… 2. 快照 做系统关键操作时&#xff0c;一定要使用快照(先将系统关机) 3.…

STM32C011开发(2)----nBOOT_SEL设置

STM32C011开发----2.nBOOT_SEL设置 概述硬件准备视频教学样品申请源码下载参考程序自举模式BOOT0设置配置 nBOOT_SEL生成STM32CUBEMX串口配置LED配置堆栈设置串口重定向主循环演示 概述 STM32CubeProgrammer (STM32CubeProg) 是一款用于编程STM32产品的全功能多操作系统软件工…

onvif协议相关:3.1.5 Digest方式获取预置位

背景 关于onvif的其实很早之前我已经在专栏中写了不少了, 使用onvif协议操作设备 但最近有陆陆续续的粉丝问我, 希望我在写一些关于 onvif的设备自动发现、预置位跳转、云台操作的博客。 满足粉丝的需求,安排。 今天我们来实现 获取预置位 准备工作 我们这里的话选择Diges…

docker 通过Dockerfile自定义的镜像部署Springboot项目

一、镜像结构介绍&#xff1a; 镜像&#xff1a;层&#xff08;Layer&#xff09;添加安装包、依赖、配置等&#xff0c;每一次操作都形成新的一层&#xff1b;基础镜像&#xff08;BaseImage&#xff09;应用依赖的系统函数库、环境、配置、文件等&#xff1b;入口&#xff0…

【Canvas与图标】GUI图标

【成图】 120*120的png图标 各种大小图&#xff1a; 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>GUI图标 Draft1</titl…

CCF GESP C++ 一级上机题(十六道题及其思路详解合集)

#include <iostream> using namespace std;int main() {// 定义起始年份、结束年份、循环变量以及用于累加的变量&#xff0c;并初始化累加变量为0int start, end, i, sum 0;// 从标准输入读取起始年份和结束年份cin >> start >> end;// 循环遍历从起始年份…

Opencv+ROS实现颜色识别应用

目录 一、工具 二、原理 概念 本质 三、实践 添加发布话题 主要代码 四、成果 五、总结 一、工具 opencvros ubuntu18.04 摄像头 二、原理 概念 彩色图像&#xff1a;RGB&#xff08;红&#xff0c;绿&#xff0c;蓝&#xff09; HSV图像&#xff1a;H&#xff0…

scala模式匹配

object test47 {def main(args: Array[String]): Unit {val id"445646546548858548648"//取出id前两位val provinceid.substring(0,2) // println(province) // if (province"42"){ // println("湖北") // }else if(province&quo…

AI加持,华为全屋智能品牌升级为“鸿蒙智家”

1.传统智能家居的困境&#xff1a;从便利到繁琐 近年来&#xff0c;智能家居因其便捷性和科技感受到消费者的青睐。然而&#xff0c;随着用户需求的多样化&#xff0c;传统智能家居的弊端逐渐显现&#xff1a; 设备连接复杂&#xff0c;品牌间兼容性不足&#xff0c;用户不得不…