当前位置: 首页 / 技术分享 / 正文
分布式锁的实现(一)

2023-01-12

   节点

  4.1. 父类的设计

  设计父类,提供连接ZooKeeper服务端的逻辑、节点操作的逻辑,所有方式实现的锁都需要继承自这个类。

  package com.qianfeng.lock;

  import org.apache.zookeeper.*;

  import org.apache.zookeeper.data.Stat;

  import java.io.IOException;

  import java.util.concurrent.CountDownLatch;

  /**

  * @author 千锋大数据教研院 - 章鱼哥

  * @company 北京千锋互联科技有限公司

  */

  public abstract class ZkLockerBase implements Watcher {

  /**

  * 操作的锁名称

  */

  protected String lockName;

  /**

  * ZooKeeper连接客户端

  */

  private ZooKeeper zkCli = null;

  /**

  * 确保可以连接到ZooKeeper客户端

  */

  private final CountDownLatch latch = new CountDownLatch(1);

  /**

  * 锁的根节点名称

  */

  protected String rootNodeName = "/zk-lock";

  /**

  * 连接到预设的服务器

  */

  public ZkLockerBase() {

  this("qianfeng01:2181,qianfeng02:2181,qianfeng03:2181");

  }

  /**

  * 连接到ZooKeeper的指定服务端

  * @param connectString 连接字符串

  */

  public ZkLockerBase(String connectString) {

  try {

  // 连接到ZooKeeper服务端

  this.zkCli = new ZooKeeper(connectString, 5000, this);

  // 等待连接成功的信号

  this.latch.await();

  // 创建根节点

  createRootNode();

  } catch (IOException | InterruptedException e) {

  e.printStackTrace();

  }

  }

  public ZkLockerBase(String connectString, String lockName) {

  this(connectString);

  this.lockName = lockName;

  }

  /**

  * 创建节点

  * @param nodeName 创建的节点名称

  * @param createMode 创建模式

  * @return 创建成功的节点名称,如果创建失败,返回null

  */

  public String createNode(String nodeName, CreateMode createMode) {

  try {

  // 创建节点,并返回创建成功之后的节点名称

  return this.zkCli.create(nodeName, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);

  } catch (KeeperException | InterruptedException ignored) {

  }

  return null;

  }

  /**

  * 删除节点

  * @param nodeName 删除的节点名称

  * @return 删除的结果

  */

  public boolean deleteNode(String nodeName) {

  try {

  // 删除节点

  this.zkCli.delete(nodeName, -1);

  return true;

  } catch (InterruptedException | KeeperException ignored) {

  }

  return false;

  }

  /**

  * 判断节点是否存在

  * @param nodeName 节点的名字

  * @return 是否存在

  */

  public boolean exists(String nodeName) {

  try {

  Stat exists = zkCli.exists(nodeName, false);

  return exists != null;

  } catch (KeeperException | InterruptedException e) {

  e.printStackTrace();

  }

  return false;

  }

  /**

  * 创建根节点,存放所有的节点或者子节点实现的锁

  */

  public void createRootNode() {

  if (!exists(this.rootNodeName)) {

  createNode(this.rootNodeName, CreateMode.CONTAINER);

  }

  }

  public String getLockName() {

  return this.rootNodeName + "/" + lockName;

  }

  public ZooKeeper getZkCli() {

  return zkCli;

  }

  @Override

  public void process(WatchedEvent event) {

  switch (event.getType()) {

  case None:

  if (event.getState().equals(Event.KeeperState.SyncConnected)) {

  // 说明连接到服务端成功

  this.latch.countDown();

  }

  case NodeCreated:

  processCreatedNode(event);

  break;

  case NodeDeleted:

  processDeleteNode(event);

  break;

  case NodeChildrenChanged:

  processChildernChange(event);

  break;

  }

  }

  // 创建节点回调

  protected void processCreatedNode(WatchedEvent event) {}

  // 删除节点回调

  protected void processDeleteNode(WatchedEvent event) {}

  // 子节点变更回调

  protected void processChildernChange(WatchedEvent event) {}

  }

  锁接口的设计

  提供所有的锁必须要实现的功能,制定锁的规范。

  package com.qianfeng.lock;

  /**

  * ZooKeeper分布式锁通用接口

  *

  * @author 千锋大数据教研院 - 章鱼哥

  * @company 北京千锋互联科技有限公司

  */

  public interface ZkLocker {

  /**

  * 上锁

  */

  boolean lock();

  /**

  * 解锁

  */

  boolean unlock();

  /**

  * 判断锁是否存在

  * @return 是否存在

  */

  boolean exists();

  }

  4.3. 节点实现的非阻塞性锁

  package com.qianfeng.lock.nodeLock;

  import com.qianfeng.lock.ZkLocker;

  import com.qianfeng.lock.ZkLockerBase;

  import org.apache.zookeeper.CreateMode;

  /**

  * @author 千锋大数据教研院 - 章鱼哥

  * @company 北京千锋互联科技有限公司

  */

  public class ZkLockerNodeNoneBlockingLocker extends ZkLockerBase implements ZkLocker {

  public ZkLockerNodeNoneBlockingLocker(String connectString, String lockName) {

  super(connectString, lockName);

  }

  public ZkLockerNodeNoneBlockingLocker(String lockName) {

  super();

  this.lockName = lockName;

  }

  /**

  * 上锁

  */

  @Override

  public boolean lock() {

  // 1. 拼接完整的节点路径

  String lockNode = this.rootNodeName + "/" + lockName;

  // 2. 创建锁

  return createNode(lockNode, CreateMode.EPHEMERAL) != null;

  }

  /**

  * 解锁

  */

  @Override

  public boolean unlock() {

  // 1. 拼接完整的节点路径

  String lockNode = this.rootNodeName + "/" + lockName;

  // 2. 删除锁

  return deleteNode(lockNode);

  }

  /**

  * 判断锁是否存在

  *

  * @return 是否存在

  */

  @Override

  public boolean exists() {

  // 1. 拼接完整的节点路径

  String lockNode = this.rootNodeName + "/" + lockName;

  // 2. 判断是否存在

  return super.exists(lockNode);

  }

  }

好程序员公众号

  • · 剖析行业发展趋势
  • · 汇聚企业项目源码

好程序员开班动态

More+
  • HTML5大前端 <高端班>

    开班时间:2021-04-12(深圳)

    开班盛况

    开班时间:2021-05-17(北京)

    开班盛况
  • 大数据+人工智能 <高端班>

    开班时间:2021-03-22(杭州)

    开班盛况

    开班时间:2021-04-26(北京)

    开班盛况
  • JavaEE分布式开发 <高端班>

    开班时间:2021-05-10(北京)

    开班盛况

    开班时间:2021-02-22(北京)

    开班盛况
  • Python人工智能+数据分析 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2020-09-21(上海)

    开班盛况
  • 云计算开发 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2019-07-22(北京)

    开班盛况
在线咨询
试听
入学教程
立即报名

Copyright 2011-2023 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号