一个注解实现分布式锁

news2024/11/24 16:00:43

文章首发微信公众号《java知路》

分布式锁原理

分布式锁是一种用于在分布式系统中协调多个节点并保证数据一致性的机制。它的目的是在分布式环境下实现互斥访问共享资源,以防止多个节点同时对共享资源进行修改或读取,从而保证数据的正确性和一致性。

实现分布式锁的一种常见方法是基于锁服务(Lock Service)。锁服务是一个可靠的中心化组件,负责协调多个节点之间的锁分配和释放。当一个节点需要获取锁时,它向锁服务发起请求,并根据锁服务的响应确定是否获得了锁。如果获得了锁,节点可以执行对共享资源的访问操作;否则,节点需要等待或执行相应的逻辑。

在锁服务中,常用的方式是使用分布式的数据存储(如 ZooKeeper、Consul 等)来实现锁的分配和释放。具体实现方式如下:

1. 当一个节点需要获取锁时,它在锁服务中创建一个临时的有序节点。节点的名称通常包含了锁的名称和一个唯一的标识符。

2. 节点根据自己创建节点的顺序来判断自己是否获得了锁。如果自己是创建节点中最小的节点(即序号最小),则表示获得了锁。

3. 如果没有获得锁,节点监听前一个节点的变化。当前一个节点被删除(即锁被释放)时,节点重新判断是否获得了锁,如果获得了,则可以执行对共享资源的操作。

通过以上方式,节点可以通过锁服务获取到分布式锁,并根据锁服务的协调来保证资源的互斥访问。当节点不再需要锁时,它会向锁服务发送释放锁的请求,锁服务将会删除相应的节点。

需要注意的是,分布式锁的实现需要考虑一系列问题,例如锁的超时处理、可重入性、死锁检测等。这些问题在实际应用中必须进行仔细的设计和处理,以确保分布式锁的正确性和可用性。

总结起来,分布式锁是一种用于在分布式系统中协调多个节点并保证数据一致性的机制。通过锁服务和分布式数据存储,可以实现对共享资源的互斥访问,从而保证数据的正确性和一致性。

在 Spring Boot 中,通过结合 Redis 使用注解来实现分布式锁是一种常见的方式。下面是一个示例:

首先,确保项目中引入了 Redis 相关的依赖:

```xml

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

```

接下来,创建一个分布式锁的注解:

```java

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface DistributedLock {

    String value() default "";

    long expire() default 30000; // 默认锁的过期时间为30秒

}

```

然后,编写一个切面类来拦截被 @DistributedLock 注解修饰的方法,并实现分布式锁的逻辑:

```java

@Aspect

@Component

public class DistributedLockAspect {

    @Autowired

    private RedisTemplate<String, String> redisTemplate;

    @Around("@annotation(distributedLock)")

    public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) throws Throwable {

        // 获取方法名作为锁的键名

        String lockKey = distributedLock.value();

        if (StringUtils.isBlank(lockKey)) {

            lockKey = joinPoint.getSignature().toLongString();

        }

        // 生成唯一的锁标识

        String lockValue = UUID.randomUUID().toString();

        // 获取锁的过期时间

        long expire = distributedLock.expire();

        // 尝试获取锁

        Boolean acquired = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, expire, TimeUnit.MILLISECONDS);

        if (acquired != null && acquired) {

            try {

                // 执行目标方法

                return joinPoint.proceed();

            } finally {

                // 释放锁

                redisTemplate.delete(lockKey);

            }

        } else {

            throw new RuntimeException("Failed to acquire lock.");

        }

    }

}

```

最后,在需要加分布式锁的方法上添加 @DistributedLock 注解即可:

```java

@Service

public class MyService {

    @DistributedLock("myLock") // 锁的键名为 myLock

    public void myMethod() {

        // 业务逻辑

    }

}

```

这样,当多个线程或多个实例调用 myMethod() 方法时,只有一个能够获得锁,其它线程或实例需要等待。等到获得锁的线程或实例执行完成后,释放锁,其它等待的线程或实例才能获取锁并执行相应的业务逻辑。

需要注意的是,使用 Redis 实现分布式锁时,需要确保 Redis 服务的高可用性和可靠性,以避免单点故障导致的锁失效问题。

图片

分布式事务4种实现方式

又被面试官问到 Redis的多线程了

分布式系统中的CAP理论,面试必问,你理解了嘛?

多线程开发带来的问题与解决方法

有了MyBatis-Flex ,再也不用mybatis-plus了

mysql分页查询数据量大的时候为什么慢,怎么优化

程序员职场晋升50条具体建议

mysql 50条 优化建议

同事离职,领导让你兼他的工作你不愿意,怎么办

MySQL 巨坑:永远不要在 MySQL 中使用 UTF-8!!请使用utf8mb4

加群交流

图片

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

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

相关文章

单向-->不带头-->非循环链表(简称:单链表)

目录 一、链表的介绍 1.链表的概念 2.单链表的节点类型 3.单链表简图 二、单链表的增删查改 1.单链表的头插 2.单链表的尾插 3.单链表的头删 4.单链表的尾删 5.单链表pos位置之后插入一个节点 6.单链表删除pos位置后的一个节点 一、链表的介绍 1.链表的概念 链表是一…

如何搬运订单(1688)

目录 下载安装与运行 任务描述 搬运具体要求&#xff08;示例&#xff09; 订单导出操作过程 搜索指定范围的订单 选择要导出的订单数据 完整的导出动画演示 切换到另一个账号 B账号批量下单的要求 下单步骤 下单设置 为啥选加采购车而不是立即下单 为啥要选自动情…

Java-方法

在编程中&#xff0c;我们也可以将频繁使用的代码封装成"帖子"(方法)&#xff0c;需要时直接拿来链接 方法就是一个代码片段. 类似于 C 语言中的 “函数” 方法定义 修饰符 返回值类型 方法名称([参数类型 形参 …]){ 方法体代码; [return 返回值]; } 这里比得C语言…

关于视频人工智能/机器视觉创业商业模式的一些思考

今年开始了我的第二次创业&#xff0c;第一次创业大家看我以前的博客就知道了&#xff0c;做音视频流媒体相关技术的&#xff0c;现在公司也已经是安徽省专精特新中小企业了&#xff0c;还好是“中小企业”&#xff0c;如果直接是专精特新企业&#xff0c;我就可以不用来视频人…

地理测绘基础知识(2)-椭球最短距离计算

在上一篇中&#xff0c;我们介绍了ECEF坐标系和经纬度的互换。 本篇&#xff0c;主要介绍已知A\B两个点的经纬度&#xff0c;如何求取椭球上的最短距离、路径。 在标准椭球面上&#xff0c;从A点运动到B点&#xff0c;距离如何&#xff0c;轨迹、每个阶段的方向又是如何呢&am…

consul安装启动流程

普通软件包安装 首先cd /opt &#xff0c;将安装包放到该目录下 下载consul安装包 进入consul官网找到自己开发平台对应的安装包下载 https://www.consul.io/downloads.html 或使用命令 wget https://releases.hashicorp.com/consul/1.6.2/consul_1.6.2_linux_amd64.zip (如果…

【K8S系列】深入解析k8s网络插件—Weave Net

序言 做一件事并不难&#xff0c;难的是在于坚持。坚持一下也不难&#xff0c;难的是坚持到底。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记论点蓝色&#xff1a;用来标记论点 Kubernetes (k8s) 是一个容器编…

MySQL数据库练习

目录 表结构 建表 插入数据 1、用SQL语句创建学生表student&#xff0c;定义主键&#xff0c;姓名不能重名&#xff0c;性别只能输入男或女&#xff0c;所在系的默认值是 “计算机”。 2、修改student 表中年龄&#xff08;age&#xff09;字段属性&#xff0c;数据类型由…

开源数据库Mysql_DBA运维实战 (修改root密码)

MySQL——修改root密码的4种方法 本文以windows为例为大家详细介绍下MySQL修改root密码的4种方法&#xff0c;大家可以可以根据的自己的情况自由选择&#xff0c;希望对大家有所帮助 方法1&#xff1a; 用SET PASSWORD命令 首先登录MySQL。 格式&#xff1a;mysql> set pass…

linux 学习————LNMP之分布式部署

目录 一、概述 二、LNMP环境部署 三、配置nginx 四、 配置php使nginx能够解析.php 五、配置mysql 六、配置discuz进行登录论坛访问测试 一、概述 LNMP代表 Linux、Nginx、MySQL、PHP&#xff0c;是一种常用的服务器架构。它由以下组件组成&#xff1a; Linux&#xff1a;作…

【2023新教程】树莓派4B开机启动-树莓派第一次启动-树莓派不使用显示器启动-树莓派从购买到启动一步一步完全版!

背景 闲来无事&#xff0c;在咸鱼上买了一个树莓派4B。买来配件都十分齐全&#xff0c;于是就想着启动来测试一下。下面是树莓派无显示器第一次启动的全过程&#xff0c;包含安装系统。 网上的教程大多需要额外使用显示器、鼠标、键盘之类的外设。然而&#xff0c;树莓派本身就…

阿里云服务器是什么?阿里云服务器有什么优缺点?

阿里云服务器是什么&#xff1f;云服务器ECS是一种安全可靠、弹性可伸缩的云计算服务&#xff0c;云服务器可以降低IT成本提升运维效率&#xff0c;免去企业或个人前期采购IT硬件的成本&#xff0c;阿里云服务器让用户像使用水、电、天然气等公共资源一样便捷、高效地使用服务器…

[数据集][目标检测]骑电动车摩托车不戴头盔数据集VOC格式1385张

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1385 标注数量(xml文件个数)&#xff1a;1385 标注类别数&#xff1a;2 标注类别名称:["y","n&q…

工业物联网数据桥接教程:Modbus 桥接到 MQTT

Modbus 介绍 Modbus 是一种串行通信协议&#xff0c;用于连接工业自动化设备&#xff0c;最初由 Modicon 公司开发&#xff0c;诞生于 1979 年&#xff0c;现在已成为通用的通讯标准之一&#xff0c;广泛用于工业自动化场景。 Modbus 采用主从模式&#xff0c;支持多种传输方…

jacoco功能测试-代码覆盖率

1、下载 jacoco 官网地址&#xff1a;EclEmma - JaCoCo Java Code Coverage Library 2、拷贝 jar 包 下载好后&#xff0c;找到这两个文件&#xff0c;然后找到被测项目 3、启动 jacocoagent&#xff0c;监控被测项目 java -javaagent:jacocoagent.jarincludes*,outputtcp…

BGP总结

前言 我们从动态路由协议的应用范围可以分为IGP&#xff08;内部网关协议&#xff09;和EGP&#xff08;外部网关协议&#xff09;。 IGP协议追求&#xff1a; 无环&#xff08;选路佳&#xff09;收敛快占用资源少 EGP协议的追求 可控性强&#xff08;管理员可以方便进行…

Rx.NET in Action 第二章学习笔记

Part 1 初入反应式扩展 2 Hello, Rx 本章节涵盖的内容: 不使用Rx的工作方式向项目中添加Rx创建你的第一个Rx应用程序 Rx 的目标是协调和统筹来自社交网络、传感器、用户界面事件等不同来源的基于事件的异步计算。例如&#xff0c;建筑物周围的监控摄像头和移动传感器会在有人靠…

激活函数总结(三):激活函数补充

激活函数总结&#xff08;三&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Softmax激活函数2.2 Softplus激活函数2.3 Mish激活函数2.4 Maxout激活函数 3. 总结 1 引言 在前面的文章中已经介绍了过去大家较为常见的激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PR…

42 | 航空公司客户价值分析

民航的竞争除了三大航空公司之间的竞争之外,还将加入新崛起的各类小型航空公司、民营航空公司,甚至国外航空巨头。航空产品生产过剩,产品同质化特征愈加明显,于是航空公司从价格、服务间的竞争逐渐转向对客户的竞争。 目前航空公司已积累了大量的会员档案信息和其乘坐航班…

vscode debug python 带参数

两种方法 第一种&#xff1a; 1&#xff0c;侧边栏选择运行和调试 2&#xff0c;请先创建一个launch.json文件 3&#xff0c;并选择配置文件为python文件 此时你的工作目录下会多一个目录.vscode和该目录下一个launch.json文件&#xff0c;该文件则配置了你的debug配置。在…