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)的更多相关文章

  1. redis分布式锁-spring boot aop+自定义注解实现分布式锁

    接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...

  2. Springboot分布式锁实践(redis)

    springboot2本地锁实践一文中提到用Guava Cache实现锁机制,但在集群中就行不通了,所以我们还一般要借助类似Redis.ZooKeeper 之类的中间件实现分布式锁,下面我们将利用自定 ...

  3. 分布式锁的实现(redis)

    1.单机锁 考虑在并发场景并且存在竞态的状况下,我们就要实现同步机制了,最简单的同步机制就是加锁. 加锁可以帮我们锁住资源,如内存中的变量,或者锁住临界区(线程中的一段代码),使得同一个时刻只有一个线 ...

  4. 基于zookeeper实现分布式锁和基于redis实现分布所的区别

    1,实现方式不同 zookeeper实现分布式锁:通过创建一个临时节点,创建的成功节点的服务则抢占到分布式锁,可做业务逻辑.当业务逻辑完成,连接中断,节点消失,继续下一轮的锁的抢占. redis实现分 ...

  5. SpringBoot进阶教程(二十七)整合Redis之分布式锁

    在之前的一篇文章(<Java分布式锁,搞懂分布式锁实现看这篇文章就对了>),已经介绍过几种java分布式锁,今天来个Redis分布式锁的demo.redis 现在已经成为系统缓存的必备组件 ...

  6. SpringBoot集成Redis 一 分布式锁 与 缓存

    1.添加依赖及配置(application.yml) <!-- 引入redis依赖 --> <dependency> <groupId>org.springfram ...

  7. 分布式缓存技术redis学习系列(五)——redis实战(redis与spring整合,分布式锁实现)

    本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...

  8. 分布式缓存技术redis系列(五)——redis实战(redis与spring整合,分布式锁实现)

    本文是redis学习系列的第五篇,点击下面链接可回看系列文章 <redis简介以及linux上的安装> <详细讲解redis数据结构(内存模型)以及常用命令> <redi ...

  9. Redis整合Spring实现分布式锁

    spring把专门的数据操作独立封装在spring-data系列中,spring-data-redis是对Redis的封装 <dependencies> <!-- 添加spring- ...

随机推荐

  1. 基于Spring MVC + Spring + MyBatis的【图书信息管理系统(二)】

    资源下载:https://download.csdn.net/download/weixin_44893902/35123371 练习点设计:添加.删除.修改 一.语言和环境 实现语言:JAVA语言. ...

  2. 使用并行Foreach优化SqlSugarMapper

    最近在迁移公司导入导出项目时,发现导出速度特别慢,大概2K数据需要导出近半个小时,通过在程序各个地方埋点,最终定位到了Sqlsugar的Mapper中,随后通过并行Foreach单独抽出Mapper中 ...

  3. Centos 7 上 查看MySQL当前使用的配置文件my.cnf的方法

    my.cnf是mysql启动时加载的配置文件,一般会放在mysql的安装目录中,用户也可以放在其他目录加载.总的来说,my.cnf类似与window中my.ini 使用locate my.cnf命令可 ...

  4. vue - public 引入 <script>报错 Uncaught SyntaxError: Unexpected token '<'

    1.现象 原本我是直接在母版引入 <script type="application/javascript" src="static/config.js" ...

  5. HDU-2032.杨辉三角(C语言描述)

    Problem Description 还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 ...

  6. 大型站点TCP/IP协议优化

    作为一个DAU上百万或千万的站点,不仅仅需要做好网站应用程序.数据库的优化,还应从TCP/IP协议层去进行相关的优化: 在我的工作中,曾使用到了以下的几种基本的优化方式: 增大最大连接数 在Linux ...

  7. 面渣逆袭:Java并发六十问,快来看看你会多少道!

    大家好,我是老三,面渣逆袭 继续,这节我们来盘一盘另一个面试必问知识点--Java并发. 这篇文章有点长,四万字,图文详解六十道Java并发面试题.人已经肝麻了,大家可以点赞.收藏慢慢看!扶我起来,我 ...

  8. 超详细的编码实战,让你的springboot应用识别图片中的行人、汽车、狗子、喵星人(JavaCV+YOLO4)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  9. Android官方文档翻译 十七 4.1Starting an Activity

    Starting an Activity 开启一个Activity This lesson teaches you to 这节课教给你 Understand the Lifecycle Callbac ...

  10. 《剑指offer》面试题24. 反转链表

    问题描述 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4-> ...