【接口防重复提交】⭐️基于RedisLockRegistry 分布式锁管理器实现

目录

前言

思路

实现方式

实践

        1.引入相关依赖

        2.aop注解

        3.切面类代码

        4.由于启动时报错找不到对应的RedisLockRegistry bean,选择通过配置类手动注入,配置类代码如下

 测试

 章末


前言

        项目中有个用户根据二维码绑定身份的接口,由于用户在操作时,可能会因为网络延迟或者其他原因多次点击提交按钮,导致重复提交相同的请求,所以需要在一定时间内限制同一个用户相同操作的重复提交,避免重复绑定的情况发生

思路

        通过Spring 的aop 功能加上分布式锁实现,aop功能可以实现切面操作有关接口,再通过分布式锁实现同一个请求在一段时间内只执行一次,保证操作的幂等性,避免数据异常

实现方式

        分布式锁选择的是 RedisLockRegistry,下面是该锁的简单介绍

RedisLockRegistry 是 Spring Integration 提供的一个基于 Redis 实现的分布式锁实用程序。可以用于在分布式环境中实现对共享资源的互斥访问。

RedisLockRegistry 使用 Redis 的原子性操作和过期时间设置来实现分布式锁。通过在 Redis 中创建一个特定的键(key),并在获取锁时将该键设置为具有过期时间的值(value)。其他线程或进程通过尝试在同一键上执行相同操作,如果能够设置成功,则表示获取到了锁,可以执行操作;否则,表示锁被其他线程或进程占用,需要等待。

实践

        1.引入相关依赖

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId></dependency><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-redis</artifactId></dependency>

        2.aop注解

        这里有两个方法,一个是提供获取锁可重试时常,另一个是获得指定的key

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/** 防止重复提交,通过分布式锁,限制同一个api接口并发时多次重复提交* @author ben.huang*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AntiReplay {/*** 获取锁重试时间,默认0ms,也就是不许重试,加锁失败,立即返回* 产生竞争时,重试获取锁的最长等待时间,在改时间内如果没有获取到锁,则失败* @return*/int tryLockTime() default 0;/*** 自定义的Key,不填的话默认“”,代码中可以自定义拼接*  需要自己提供默认的话,在注解使用时赋值即可* @return*/String key() default "";
}

        3.切面类代码

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;/*** @author ben.huang*/
@Component
@Aspect
@Slf4j
public class AntiReplayAspect {@Resourceprivate RedisLockRegistry redisLockRegistry;@Pointcut("@annotation(antiReplay)")public void pointcut(AntiReplay antiReplay){}@Around(value = "pointcut(antiReplay)")public Object around(ProceedingJoinPoint proceedingJoinPoint,AntiReplay antiReplay) throws Throwable{int tryLockTime = antiReplay.tryLockTime();Object result = null;String name = "testRedisLock-";String path = antiReplay.key();//这里简化了,使用时可以使用用户唯一辨识(比如用户id)拼接keyString key = name + path;Lock lock = redisLockRegistry.obtain(key);boolean isSuccess = lock.tryLock(tryLockTime, TimeUnit.MILLISECONDS);if(isSuccess){log.info("获取锁 key = [{}]",key);try{result = proceedingJoinPoint.proceed();}finally{if(isSuccess){lock.unlock();log.info("释放锁 success, key = [{}]",key);}}}else{log.info("获取锁失败 fial ,key = [{}]",key);throw new Exception("error");}return result;}
}

        4.由于启动时报错找不到对应的RedisLockRegistry bean,选择通过配置类手动注入,配置类代码如下

Description: A component required a bean of type 'org.springframework.integration.redis.util.RedisLockRegistry' that could not be found.

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;/*** @author ben.huang*/
@Configuration
public class AntiReplayConfig {@Beanpublic RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory){RedisLockRegistry redisLockRegistry = new RedisLockRegistry(redisConnectionFactory, "my-lock-key");return redisLockRegistry;}}

 测试

        1.因为该场景是在并发时发生的,所以可以选择压测的方式模拟下并发场景,创建一个简单的测试接口,登录成功则在控制台打印信息,否则抛出异常

    @AntiReplay(key = "userLogin")@PostMapping(value = "/login")public BaseResult login(String username, String password) {UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));if(user==null || !user.getPassword().equals(password)) {throw new RuntimeException("error while logining");}System.out.println(" login success!");return BaseResult.success();}

         2.压测工具使用的是APIpost接口测试工具,不加防重复注解时启动项目调用接口的结果如下

可以看到在没有加锁的情况下,所有请求全部成功

        3.加上注解后再次压测,结果如下 ,可以看到大部分请求都失败了,为什么还有这么多请求成功的?是因为获取到锁的线程会释放锁,后面的线程还可以接着抢,看控制台也会发现有很多次释放锁记录

 章末

        文章到这里就结束了~

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

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

相关文章

【Unity动画】Unity如何导入序列帧动画(GIF)

Unity 不支持GIF动画的直接播放&#xff0c;我们需要使用序列帧的方式 01准备好序列帧 02全部拖到Unity 仓库文件夹中 03全选修改成精灵模式Sprite 2D ,根据需要修改尺寸&#xff0c;点击Apply 04 创建一个空物体 拖动序列上去 然后全选所有序列帧&#xff0c;拖到这个空物体…

SpringBoot中使用验证码easy-captcha

easy-captcha使用的大概逻辑: 当一个请求发送到后端服务器请求验证,服务器使用easy-captcha生成一个验证码图片,并通过session将验证信息保存在服务器,当用户登录校验时候,会从ession中取出对比是否一致 但是前后端分离之后 由于跨域问题 以上就无法实现了 下面这种情况没…

完整指南:如何使用 Stable Diffusion API

Stable Diffusion 是一个先进的深度学习模型&#xff0c;用于创造和修改图像。这个模型能够基于文本描述来生成图像&#xff0c;让机器理解和实现用户的创意。使用这项技术的关键在于掌握其 API&#xff0c;通过编程来操控图像生成的过程。 在探索 Stable Diffusion API 的世界…

Linux进程通信补充——System V通信

三、System V进程通信 ​ System V是一个单独设计的内核模块&#xff1b; ​ 这套标准的设计不符合Linux下一切皆文件的思想&#xff0c;尽管隶属于文件部分&#xff0c;但是已经是一个独立的模块&#xff0c;并且shmid与文件描述符之间的兼容性做的并不好&#xff0c;网络通…

【K8S】docker和K8S(kubernetes)理解?docker是什么?K8S架构、Master节点 Node节点 K8S架构图

docker和K8S理解 一、docker的问世虚拟机是什么&#xff1f;Docker的问世&#xff1f;docker优点及理解 二、Kubernetes-K8SK8S是什么&#xff1f;简单了解K8S架构Master节点Node节点K8S架构图 一、docker的问世 在LXC(Linux container)Linux容器虚拟技术出现之前&#xff0c;业…

云手机的数据安全有保障吗?

随着移动互联网的迅速发展&#xff0c;云手机作为一种新兴的移动终端技术&#xff0c;正在逐渐受到人们的关注和应用。然而&#xff0c;对于云手机而言&#xff0c;数据安全问题一直是人们关注的焦点之一。本文将探讨云手机的数据安全性&#xff0c;并分析其是否具备足够的保障…

打造坚不可摧的防线:容灾策略的实践与探索

在当今这个信息化时代&#xff0c;数据已成为企业最宝贵的财富之一。因此&#xff0c;保护数据免受意外损坏或灾难性事件的影响变得至关重要。这就需要企业建立一个有效的容灾体系&#xff0c;来确保业务连续性和数据安全。 容灾&#xff0c;即灾难恢复&#xff08;Disaster Re…

huawei 华为交换机 配置手工模式链路聚合示例

组网需求 如 图 3-21 所示&#xff0c; SwitchA 和 SwitchB 通过以太链路分别都连接 VLAN10 和 VLAN20 的网络&#xff0c;SwitchA 和 SwitchB 之间有较大的数据流量。 用户希望SwitchA 和 SwitchB 之间能够提供较大的链路带宽来使相同 VLAN 间互相通信。 同时用户也希望能够提…

基于Java+SpringBoot+Vue前后端分离婚纱影楼管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行交流合作✌ 主要内容&#xff1a;SpringBoot、Vue、SSM、HLM…

MacBook远程桌面Windows使用Microsoft Remote Desktop for Mac_亲测使用

MacBook远程桌面Windows使用Microsoft Remote Desktop for Mac_亲测使用 像Windows上有自带的远程桌面连接软件.MacBook没有自带的远程连接Windows桌面的工具,需要安装软件来实现. 像远程桌面控制软件一般有 TeamViewer、向日葵远程控制, ToDesk, Microsoft Remote Desktop f…

vue实现element-UI中table表格背景颜色设置

目前在style中设置不了&#xff0c;那么就在前面组件给设置上 :header-cell-style"{ color: #ffffff, fontSize: 14px, backgroundColor: #0E2152 }" :cell-style"{ color: #ffffff, fontSize: 14px, backgroundColor: #0E2152 }"

Javaweb的学习19_CSS概念+css与html的结合方式

CSS CSS&#xff1a;页面美化和布局控制 1. 概念&#xff1a;Cascading Style Sheets 层叠样式表 层叠&#xff1a;多个样式可以作用在同一个html的元素(标签)上&#xff0c;同时生效 2. 好处&#xff1a; 1.功能强大 2.将内容展示(HTML)和样式控制(CSS)分离 *降低耦合度。解耦…

电话机器人语音识别用哪家更好精准度更高。

语音识别系统的选择取决于你的具体需求&#xff0c;包括但不限于识别精度、速度、易用性、价格等因素。以下是一些在语音识别领域表现较好的公司和产品&#xff1a; 科大讯飞&#xff1a;科大讯飞是中国最大的语音识别技术提供商之一&#xff0c;其语音识别技术被广泛应用于各…

基于spring boot的汽车4s店管理系统

摘 要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;汽车4s店管理系统当然不能排除在外。汽车4s店管理系统是在实际应用和软件工程的开发原理之上&#xff0c;运用java语言以及SpringBoot框架…

[HackMyVM]靶场 Zon

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

CSDN 停更通知

CSDN 不再更新&#xff0c;欢迎关注我的微信公众号&#xff0c;分享更多有趣的技术内容。 如果大家有任何疑问&#xff0c;或者感兴趣的话题&#xff0c;都可以通过微信公众号与我交流&#xff0c;相互学习&#xff0c;相互成长。

Css提高——Css3的新增选择器

目录 1、Css3新增选择器列举 2、属性选择器 2.1、语法 2.2、代码&#xff1a; 2.3、效果图 3、结构伪类选择器 3.1、语法 3.2、代码 3.3、效果图 3.4、nth&#xff1a;child&#xff08;n&#xff09;的用法拓展 nth-child&#xff08;n&#xff09;与nth-of-type&#x…

21年电赛-送药小车—基于OpenMV的寻迹+检测路口+数字识别(多模版匹配)(附代码)

我们花费了四天时间打了一场21年的电赛改编题——智能送药小车。虽然结果不尽人意&#xff0c;但这是我学习32以来第一次正式的打比赛&#xff0c;对我来说要学习的东西&#xff0c;所增长的经验真的特别多&#xff08;虽然基本上都是学长在出力~&#xff09;下来我就把关于这次…

3.18数据结构

一、数据结构----->用来组织存储数据 一组用来保存一种或多种特定关系的数据的集合&#xff08;组织和存储数据&#xff09; 程序 数据结构 算法 MVC&#xff1a;软件设计架构 M&#xff1a;数据的管理&#xff08;数据结构&#xff09; V&#xff1a;视图&#xff0c…

B003-springcloud alibaba 服务治理 nacos discovery ribbon feign

目录 服务治理服务治理介绍什么是服务治理相关方案 nacos实战入门搭建nacos环境安装nacos启动nacos访问nacos 将商品微服务注册进nacos将订单微服务注册进nacos订单服务通过nacos调用商品服务 实现服务调用的负载均衡什么是负载均衡代码实现负载均衡增加一个服务提供者自定义实…