SpringBoot结合ZooKeeper实现分布式锁
ZooKeeper 一个中心化的服务, 用于维护配置信息, 命名服务(naming), 提供分布式同步和集群服务(group services)。它是一个开源的分布式应用程序协调服务, 作为 Google Chubby的一个开源实现, 是Hadoop和Hbase的重要组件。ZooKeeper 的目标是封装好复杂易出错的关键服务, 暴露简单易用、高效、稳定的接口给用户使用, 提供基于java和C的接
ZooKeeper 介绍
ZooKeeper 一个中心化的服务, 用于维护配置信息, 命名服务(naming), 提供分布式同步和集群服务(group services)。
它是一个开源的分布式应用程序协调服务, 作为 Google Chubby的一个开源实现, 是Hadoop和Hbase的重要组件。 ZooKeeper 的目标是封装好复杂易出错的关键服务, 暴露简单易用、高效、稳定的接口给用户使用, 提供基于java和C的接口。
Zookeeper 的核心实现是一个分布式的数据存储系统,其内部采用 ZAB 协议(Zookeeper Atomic Broadcast)进行主从复制,确保了数据的一致性和可靠性。在 Zookeeper 中,数据存储采用了一种称为“Znode”的数据模型,类似于 Unix 文件系统。
Znode 是 Zookeeper 中最基本的数据单元,是一个有层级的树形结构,每个节点都有一个路径,其中根节点为“/”,子节点路径会在父节点路径的基础上加上相对路径,最终形成一棵完整的树形结构。
Zookeeper的设计目标
简单
ZooKeeper 允许分布式的进程之间通过一个共享的层级命名空间(hierarchinal namespace, 和文件系统类似)进行协调。
ZK 实现了高性能、高可用和严格顺序访问, 是的它可以用于大规模分布式系统, 无单点故障问题, 和复杂的同步原语。
ZK 提供了简单的编程接口。
复制的(replicated)
ZooKeeper和其它的分布式进程一样, 也是一个集群的主机作为一个整体。
有序(ordered)
ZooKeeper用一个数字表示每一次的更新, 以反映所有 ZooKeeper 事务的顺序。后续可以利用这个顺序来实现诸如同步原语之类的高级抽象。
快速(fast)
ZooKeeper在读多写少的负载中性能尤其高, 读写比例大概处于 10:1 时表现最好。
Zookeeper的数据模型
Zookeeper使用一种树状数据模型来表示数据结构。每个节点在这个树状结构中都有一个唯一的路径,这个路径由节点的绝对路径组成。绝对路径是一个以斜杠(/)开头的字符串,表示从根节点到当前节点的路径。
Zookeeper的数据模型包括以下几个组成部分:
节点:节点是Zookeeper中的基本数据结构,它可以存储数据和元数据。
路径:路径是节点的唯一标识,用于表示节点在树状结构中的位置。
父节点:每个节点都有一个父节点,表示它在树状结构中的父节点。
子节点:每个节点都可以有多个子节点,表示它在树状结构中的子节点。
Zookeeper的数据操作
Zookeeper提供了一系列的数据操作接口,用于对数据进行CRUD操作。这些操作接口包括:
create:创建一个新节点。
get:获取一个节点的数据。
set:设置一个节点的数据。
delete:删除一个节点。
exists:检查一个节点是否存在。
sync:同步一个节点的数据。
Zookeeper实现分布式锁
分布式锁主要用于在分布式环境中保护跨进程、跨主机、跨网络的共享资源实现互斥访问,以达到保证数据的一致性。Zookeeper实现分布式锁是通过持久节点和临时顺序节点来完成的,实现思路如下:
获取锁:
1. 首先我们要有一个持久节点/locks,客户端获取锁就是在locks下创建临时顺序节点。
2. 假设客户端 1 创建了/locks/lock1节点,创建成功之后,会判断 lock1是否是 /locks 下最小的子节点。
3. 如果 lock1是最小的子节点,则获取锁成功。否则,获取锁失败。
4. 如果获取锁失败,则说明有其他的客户端已经成功获取锁。客户端 1 并不会不停地循环去尝试加锁,而是在前一个节点比如/locks/lock0上注册一个事件监听器。这个监听器的作用是当前一个节点释放锁之后通知客户端 1(避免无效自旋),这样客户端 1 就加锁成功了。
释放锁:
1. 成功获取锁的客户端在执行完业务流程之后,会将对应的子节点删除。
2. 成功获取锁的客户端在出现故障之后,对应的子节点由于是临时顺序节点,也会被自动删除,避免了锁无法被释放。
3. 我们前面说的事件监听器其实监听的就是这个子节点删除事件,子节点删除就意味着锁被释放。
Curator
实际项目中,推荐使用 Curator 来实现 ZooKeeper 分布式锁。Curator 是 Netflix 公司开源的一套 ZooKeeper Java 客户端框架,相比于 ZooKeeper 自带的客户端 zookeeper 来说,Curator的封装更加完善,各种API都可以比较方便地使用。Curator主要实现了下面四种锁:
InterProcessMutex:分布式可重入排它锁
InterProcessSemaphoreMutex:分布式不可重入排它锁
InterProcessReadWriteLock:分布式读写锁
InterProcessMultiLock:将多个锁作为单个实体管理的容器,获取锁的时候获取所有锁,释放锁也会释放所有锁资源(忽略释放失败的锁)。
以下是使用Curator的部分代码示例
在项目的pom.xml中引入Curator依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>5.6.0</version>
</dependency>
业务代码测试:
public String createOrderCurator(Integer productId, Integer count) throws Exception {
InterProcessMutex lock = new InterProcessMutex(curatorFramework, "/lockPath");
//try to get lock.
if(lock.acquire(5,TimeUnit.SECONDS)) {
try {
//todo 模拟业务操作
Thread.sleep(2000);
return "create order finished!";
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.release();
}
}
return "error to create lock!";
}
福利来了,京东618无门槛红包,速抢,亲测可用!!!
更多推荐
所有评论(0)