springboot实现分布式锁(spring integration,redis)
Springboot实现分布式锁(Spring Integration+Redis)
一.在项目的pom.xml中添加相关依赖
1)Spring Integration依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
2)Spring Integration Redis依赖
<dependency> 
  <groupId>org.springframework.integration</groupId> 
  <artifactId>spring-integration-redis</artifactId> 
</dependency>
3)Spring Data Redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.yml添加配置
spring:
redis:
port: 6379
host: ***.***.***.***
password: 123456
RedisLockRegistry的配置
package com.lzx.demo.configuration; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry; /**
* 描述:锁配置
*
* @Auther: lzx
* @Date: 2019/6/17 15:06
*/
@Configuration
public class RedisLockConfiguration { @Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory){
return new RedisLockRegistry(redisConnectionFactory,"spring-cloud");
} }
二.使用分布式锁
1)自定义分布式锁的注解RedisLock
/**
* 用于标记redis锁
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisLock { /**
* 可使用SpEL传方法参数
* @return
*/
String value() default ""; /**
* redis锁的key值
* @return
*/
String lockKey() default "";
}
2)使用aop实现锁的获取和释放(切面中的具体逻辑根据实际情况来写)
package com.apps.lock; import com.apps.bcodemsg.MsgResponse;import com.apps.redis.util.SerializeUtil;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Component; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock; /**
* redis分布式锁的切面
*/
@Aspect
@Component
public class RedisLockAspect { @Autowired
private RedisLockRegistry redisLockRegistry; @Around(value = "@annotation(redisLock)")
public synchronized Object redisLock(ProceedingJoinPoint joinPoint,
RedisLock redisLock) {
Logger mLog = LoggerFactory.getLogger(SerializeUtil.class);
Object output = null;
try { MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Object[] arguments = joinPoint.getArgs();
Field[] field = arguments[0].getClass().getDeclaredFields();
String value = "";
for (int j = 0; j < field.length; j++) { boolean fieldHasAnno = field[j].isAnnotationPresent(RedisLockKey.class);
if (fieldHasAnno) {
RedisLockKey fieldAnno = field[j].getAnnotation(RedisLockKey.class);
//输出注解属性
String age = fieldAnno.value();
String name = field[j].getName();
name = name.substring(0, 1).toUpperCase() + name.substring(1);
Method m = arguments[0].getClass().getMethod("get" + name);
value = (String) m.invoke(arguments[0]);
System.out.println(value);
}
}
// 获取锁的key
Object lockKey = value;
if (lockKey == null || StringUtils.isBlank((String) lockKey)) {
lockKey = "publistLock";
}
Lock lock = redisLockRegistry.obtain(lockKey); try {
boolean ifLock = lock.tryLock(3, TimeUnit.SECONDS);
// mLog.info("线程[{}]是否获取到了锁:{ }", Thread.currentThread().getName(), ifLock);
/*
* 可以获取到锁,说明当前没有线程在执行该方法
*/
if (ifLock) {
output = joinPoint.proceed();
} else {
MsgResponse msgResponse = new MsgResponse();
msgResponse.setCode(400);
msgResponse.setMsg("服务异常!!!");
// mLog.info("线程[{}]未获取到锁,目前锁详情信息为:{}", Thread.currentThread().getName(), lock);
return msgResponse;
}
} catch (Exception e) {
// mLog.error("执行核心奖励扫描时出错:{}", e.getMessage());
} finally {
// mLog.info("尝试解锁[{}]", lockKey);
try {
lock.unlock();
// mLog.info("[{}]解锁成功", lockKey);
} catch (Exception e) {
// mLog.error("解锁dealAction出错:{}", e.getMessage());
}
}
} catch (Throwable e) {
mLog.error("aop redis distributed lock error:{}", e.getLocalizedMessage());
}
return output;
} }
3)使用RedisLock注解实现分布式锁
@LzxLockDistributed(value = "redisLockRegistry",time = 60)
public String redisLockTest() throws InterruptedException {
if(inventory >= 5){
return "已经抢购完了~~~";
}
String s = strArr[inventory];
Thread.sleep(10*1000);
inventory++;
return s; }
本文部分转载自:
https://blog.csdn.net/github_35976996/article/details/93909359
springboot实现分布式锁(spring integration,redis)的更多相关文章
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
		
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
 - Springboot分布式锁实践(redis)
		
springboot2本地锁实践一文中提到用Guava Cache实现锁机制,但在集群中就行不通了,所以我们还一般要借助类似Redis.ZooKeeper 之类的中间件实现分布式锁,下面我们将利用自定 ...
 - 分布式锁的实现(redis)
		
1.单机锁 考虑在并发场景并且存在竞态的状况下,我们就要实现同步机制了,最简单的同步机制就是加锁. 加锁可以帮我们锁住资源,如内存中的变量,或者锁住临界区(线程中的一段代码),使得同一个时刻只有一个线 ...
 - 基于zookeeper实现分布式锁和基于redis实现分布所的区别
		
1,实现方式不同 zookeeper实现分布式锁:通过创建一个临时节点,创建的成功节点的服务则抢占到分布式锁,可做业务逻辑.当业务逻辑完成,连接中断,节点消失,继续下一轮的锁的抢占. redis实现分 ...
 - SpringBoot进阶教程(二十七)整合Redis之分布式锁
		
在之前的一篇文章(<Java分布式锁,搞懂分布式锁实现看这篇文章就对了>),已经介绍过几种java分布式锁,今天来个Redis分布式锁的demo.redis 现在已经成为系统缓存的必备组件 ...
 - SpringBoot集成Redis 一 分布式锁 与 缓存
		
1.添加依赖及配置(application.yml) <!-- 引入redis依赖 --> <dependency> <groupId>org.springfram ...
 - 分布式缓存技术redis学习系列(五)——redis实战(redis与spring整合,分布式锁实现)
		
本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...
 - 分布式缓存技术redis系列(五)——redis实战(redis与spring整合,分布式锁实现)
		
本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...
 - Redis整合Spring实现分布式锁
		
spring把专门的数据操作独立封装在spring-data系列中,spring-data-redis是对Redis的封装 <dependencies> <!-- 添加spring- ...
 
随机推荐
- Java代码实体类生成SQL语句(Java实体类转数据库)
			
有的时候把数据库删了,如果照着实体类重新创建数据库的话比较麻烦,可以使用这个工具,把代码复制到项目里面设置一下即可把Java代码中的实体类转换为SQL语句输出为一个文件,打开执行命令即可. 下载:ht ...
 - 【】Nessus安全测试插件编写教程
			
Nessus安全测试插件编写教程 作者:Renaud Deraison 翻译:nixe0n 1.怎样编写一个高效的Nessus安全测试插件 在Nessus安全测试系统中, 所有的安全测试都是由ness ...
 - docker容器的本质
			
1. 容器其实就是Linux下一个特殊的进程: 2. Docker容器通过namespace实现进程隔离通过cgroups实现资源限制: 3. Docker镜像(rootfs)是一个操作系统的所有文件 ...
 - linux 之 nginx安装步骤
			
配置规划 用户 lzh 用户目录 /lzh 下载 进入官网下载nginx http://nginx.org/download/ 安装 解压 cd /lzh/app tar -zxvf nginx-1 ...
 - linux(CentOS7) 之 jdk1.8 下载及安装
			
下载 一.百度搜索oracle,进入官网(或直接进入官网https://www.oracle.com) 二.选择 products 下的 java 三.选择Download Java 四.往下翻找到J ...
 - Linux上天之路(十六)之Shell编程一
			
用户在命令行输入命令后,一般情况下Shell会fork并exec该命令,但是Shell的内建命令例外,执行内建命令相当于调用Shell进程中的一个函数,并不创建新的进程.以前学过的cd.alias.u ...
 - [转]Vue之引用第三方JS插件
			
1.绝对路径引入,全局使用. 在index.html文件中使用script标签引入插件. 该种方式就是上面演示ckplayer插件使用的方式. 备注: 这种方式的引用,会在开启ESLint时,报错,可 ...
 - Sentry 开发者贡献指南 - Django Rest Framework(Serializers)
			
Serializer 用于获取复杂的 python 模型并将它们转换为 json.序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型. 在 Sentry,我们有两种不同类型 ...
 - Termux劣质的入门指南
			
直入主题: 1.1 下载安装 Google下载(有条件的用!) F-droid下载(建议使用!) 也可以去酷安下载! 1.2 配置 apt update && apt upgrade ...
 - 《剑指offer》面试题46. 把数字翻译成字符串
			
问题描述 给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 "a" ,1 翻译成 "b",--,11 翻译成 "l",--,25 ...