01 安装并允许zookeeper

  1. 安装jdk
  2. 官网下载zookeeper的压缩包,我这里下载的是3.4.10版本
  3. 解压后进入到zookeeper-3.4.10/conf,修改zoo_sample.cfg文件修改为zoo.cfg文件
mv zoo_sample.cfg zoo.cfg
  • 1
  1. 打开zoo.cfg文件,修改dataDir路径。修改后在/usr/local/zookeeper-3.4.10目录创建文件夹mkdir zkData
dataDir=/usr/local/zookeeper-3.4.10/zkData
  • 1
  1. 启动zookeeper
/usr/local/zookeeper-3.4.10/bin/zkServer.sh start
  • 1

02 springboot应用配置CuratorFramework

  1. 导入maven依赖
<!-- zookeeper 客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency> <dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
  1. 配置CuratorFramework

zookeeper的默认端口是2181

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling
@EnableJpaAuditing
@SpringBootApplication
public class MyDemoApplication { public static void main(String[] args) {
SpringApplication.run(MyDemoApplication.class, args);
} @Bean
public CuratorFramework curatorFramework() {
return CuratorFrameworkFactory.newClient("127.0.0.1:2181", new RetryNTimes(5, 1000));
}
}
  1. 启动CuratorFramework客户端
import org.apache.curator.framework.CuratorFramework;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service; /**
* 实现了ApplicationRunner接口后,当容器启动后,会执行实现的run方法
*
* @author 594781919
*/
@Service
public class StartService implements ApplicationRunner { @Autowired
private CuratorFramework curatorFramework; @Autowired
private ListenerService listenerService; @Override
public void run(ApplicationArguments applicationArguments) {
// 非常重要!!!Start the client. Most mutator methods will not work until the client is started
curatorFramework.start();
System.out.println("zookeeper client start");
// 初始化监听方法
listenerService.listener();
}
}

03 使用zookeeper实现集群只一个应用实例执行定时任务

当我们启动多个实例时,需要其中一个实例执行定时任务,其它实例不执行。

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.LeaderLatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import java.io.IOException;
import java.util.Date; /**
* 实现多个应用实例只一个执行定时任务
*
* @author 594781919@qq.com
*/
@Service
public class TimerTaskService { @Autowired
private CuratorFramework curatorFramework; @Value("${server.port}")
private String port; @Scheduled(cron = "0/5 * * * * *")
public void task() {
LeaderLatch leaderLatch = new LeaderLatch(curatorFramework, "/timerTask");
try {
leaderLatch.start();
// Leader选举需要一些时间,等待2秒
Thread.sleep(2000);
// 判断是否为主节点
if (leaderLatch.hasLeadership()) {
System.out.println(new Date() + " port=" + port + " 是领导");
// 定时任务的业务逻辑代码
} else {
System.out.println(new Date() + " port=" + port + " 是从属");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
leaderLatch.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

04 使用zookeeper实现分布式锁

import com.igola.domain.Employee;
import com.igola.repository.EmployeeRepository;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @author 594781919@qq.com
*/
@RestController
public class EmployeeController {
@Autowired
private EmployeeRepository employeeRepository; @Autowired
private CuratorFramework curatorFramework; @GetMapping("/emp/save")
public Employee save(String name) { // 获取锁
InterProcessSemaphoreMutex balanceLock = new InterProcessSemaphoreMutex(curatorFramework, "/zktest" + name);
Employee employee = new Employee();
try {
// 执行加锁操作
balanceLock.acquire();
System.out.println("已经加锁了, name=" + name);
employee.setName(name);
if ("abc".equals(name)) {
Thread.sleep(30000);
}
employee.setAge((int) (Math.random() * 100));
employee.setSex(false);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 释放锁资源
balanceLock.release();
} catch (Exception e) {
e.printStackTrace();
}
} employeeRepository.save(employee); return employee;
}
}
  • 1
  • 2

05 使用zookeeper实现调度任务

当我们在启动多个服务后,访问了其中一个服务,执行了一些方法。然后我们需要其它服务也要执行这些方法,就需要用到NodeCache。

比如我们把一些数据缓存到Map对象中,当需要更新这个Map对象的数据时,我们就可以用NodeCache将每个服务都更新自己的Map对象。

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.utils.CloseableUtils;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Service; import javax.annotation.PreDestroy;
import java.util.Date; /**
* @author 594781919
*/
@Service
public class ListenerService {
private final CuratorFramework curatorFramework;
private NodeCache nodeCache; public static final String path = "/hello/world"; public ListenerService(CuratorFramework curatorFramework) {
this.curatorFramework = curatorFramework; } public void listener() {
try {
// 创建路径
Stat stat = curatorFramework.checkExists().forPath(path);
if (stat == null) {
curatorFramework.create().creatingParentsIfNeeded().forPath(path);
}
} catch (Exception e) {
e.printStackTrace();
}
nodeCache = new NodeCache(curatorFramework, path);
// 添加监听的路径改变后需要执行的任务
nodeCache.getListenable().addListener(this::run);
try {
nodeCache.start();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("开始监听......");
} @PreDestroy
public void preDestroy() {
CloseableUtils.closeQuietly(nodeCache);
} public void notifyNodeCache() {
try {
curatorFramework.setData().forPath(path);
} catch (Exception e) {
e.printStackTrace();
}
} // 需要执行的调度任务
private void run() {
System.out.println(new Date().toLocaleString() + ", 开始执行监听任务");
}
}

springboot整合zookeeper实现分布式锁的更多相关文章

  1. springboot整合curator实现分布式锁

    理论篇: Curator是Netflix开源的一套ZooKeeper客户端框架. Netflix在使用ZooKeeper的过程中发现ZooKeeper自带的客户端太底层, 应用方在使用的时候需要自己处 ...

  2. SpringBoot电商项目实战 — Zookeeper的分布式锁实现

    上一篇演示了基于Redis的Redisson分布式锁实现,那今天我要再来说说基于Zookeeper的分布式现实. Zookeeper分布式锁实现 要用Zookeeper实现分布式锁,我就不得不说说zo ...

  3. java springboot整合zookeeper入门教程(增删改查)

    java springboot整合zookeeper增删改查入门教程 zookeeper的安装与集群搭建参考:https://www.cnblogs.com/zwcry/p/10272506.html ...

  4. ZooKeeper学习(二)ZooKeeper实现分布式锁

    一.简介 在日常开发过程中,大型的项目一般都会采用分布式架构,那么在分布式架构中若需要同时对一个变量进行操作时,可以采用分布式锁来解决变量访问冲突的问题,最典型的案例就是防止库存超卖,当然还有其他很多 ...

  5. 6 zookeeper实现分布式锁

    zookeeper实现分布式锁 仓库地址:https://gitee.com/J_look/ssm-zookeeper/blob/master/README.md 锁:我们在多线程中接触过,作用就是让 ...

  6. zookeeper实现分布式锁服务

    A distributed lock base on zookeeper. zookeeper是hadoop下面的一个子项目, 用来协调跟hadoop相关的一些分布式的框架, 如hadoop, hiv ...

  7. [ZooKeeper.net] 3 ZooKeeper的分布式锁

    基于ZooKeeper的分布式锁 ZooKeeper 里实现分布式锁的基本逻辑: 1.zookeeper中创建一个根节点(Locks),用于后续各个客户端的锁操作. 2.想要获取锁的client都在L ...

  8. 基于 Zookeeper 的分布式锁实现

    1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个“类 Unix/Linu ...

  9. zookeeper的分布式锁

    实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,其中前两种方案网络上有很多资料可以参考,本文不做展开.我们来看下使用Zookeeper如何实现分布式锁. 什么是 ...

随机推荐

  1. Docker 基础备忘录

    Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机).bare metal. ...

  2. session过期跳转到登陆页面并解决跳出iframe问题

    首先,先转载如下这篇博主写的关于后台系统使用iframe不能跳出的问题,地址:https://blog.csdn.net/xiaocen99/article/details/38521649 在ifr ...

  3. AgileTC linux部署

    简介 AgileTC是一套敏捷的测试用例管理平台,支持测试用例管理.执行计划管理.进度计算.多人实时协同等能力,方便测试人员对用例进行管理和沉淀.产品以脑图方式编辑可快速上手,用例关联需求形成流程闭环 ...

  4. 一个很多人不知道的SpringBoot小技能!!

    大家好,我是冰河~~ 最近,发现很多小伙伴在修改了SpringBoot的配置文件后,都要重新编译整个项目,极大的浪费了开发时间.我身边就有很多小伙伴一直是这样做的.那么,有没有什么方式能够修改配置文件 ...

  5. robotframework - selenium Api介绍

    一.介绍下selenium常用的api *** Settings ***Library SeleniumLibraryResource baidu业务.txtResource UI分层.txt *** ...

  6. [考试总结]noip模拟23

    因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...

  7. 第十五篇 -- QListWidget与QToolButton(界面)

    效果图: 这还只是一个界面,并没有实现相应功能. 先看下这图的构成吧. 工具栏的就是将Action拖上去,这部分前面已经介绍过了,那就看下面这部分的构图. 1.左侧是一个工具箱(ToolBox)组件, ...

  8. Qt 入门 ---- 布局管理

    这是运行后的程序界面: 这是点击右上角"最大化"之后的程序界面: 接下来讲一下如何进行自动布局解决窗口拉伸问题. ① 原理: 在项目"设计"模式的左侧有如下两个 ...

  9. jvm源码解读--18 Java的start()方法解读 以及 wait 和notify流程图

    drawwed by 张艳涛 and get info from openjdk8 还有一个图

  10. Android内存溢出、内存泄漏常见案例及最佳实践总结

    内存溢出是Android开发中一个老大难的问题,相关的知识点比较繁杂,绝大部分的开发者都零零星星知道一些,但难以全面.本篇文档会尽量从广度和深度两个方面进行整理,帮助大家梳理这方面的知识点(基于Jav ...