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/25706959 一.语言和环境 1. 实现语言:Java语言 2. 环境要求:ecl ...

  2. 编写Java程序,在子类老虎中重写父类动物的吃食方法

    返回本章节 返回作业目录 需求说明: 在子类老虎中重写父类动物的吃食方法 实现思路: 在子类老虎中重写父类动物的吃食方法的实现思路如下: 创建各种动物的父类Animal类,在该类中定义eat()方法. ...

  3. Swoole 中使用 Atomic 实现进程间无锁计数器

    使用示例: $atomic = new Swoole\Atomic(); $serv = new Swoole\Server('127.0.0.1', '9501'); $serv->set([ ...

  4. Thrift框架-具体使用

    1.前言 使用thrift心得: (1)thrift是一个RPC的框架  ,RPC是远程过程调用协议:用于进行可扩展且跨语言的服务的开发,以构建在C++.Java.Python.PHP.Ruby.Er ...

  5. CSS相关知识及入门

    CSS(层叠样式表) 作用 修饰HTML页面,美化 CSS代码规范 放置规范 在<style>标签内容体中书写样式代码 <style>标签放置在<head>标签内. ...

  6. 关于less使用初学者常犯错误

    1.多层嵌套 2.定义变量复用性不高 3.方法定义多余参数.

  7. SparkSQL学习笔记

    概述 冠状病毒来临,宅在家中给国家做贡献之际,写一篇随笔记录SparkSQL的学习笔记,目的有二,一是记录整理之前的知识作为备忘录,二是分享技术,大家共同进步,有问题也希望大家不吝赐教.总体而言,大数 ...

  8. 18个示例详解 Spring 事务传播机制(附测试源码)

    什么是事务传播机制 事务的传播机制,顾名思义就是多个事务方法之间调用,事务如何在这些方法之间传播. 举个例子,方法 A 是一个事务的方法,方法 A 执行的时候调用了方法 B,此时方法 B 有无事务以及 ...

  9. Android学习笔记4

    activity配置文件 //AndroidMainifest.xml <?xml version="1.0" encoding="utf-8"?> ...

  10. Android学习笔记3

    (5)练习做一个实现两个数相乘的APP ①.java代码: //MainActivity.java package com.example.hello; import android.content. ...