关于重复请求,指的是我们服务端接收到很短的时间内的多个相同内容的重复请求。而这样的重复请求如果是幂等的(每次请求的结果都相同,如查询请求),那其实对于我们没有什么影响,但如果是非幂等的(每次请求都会对关键数据造成影响,如删除关系、建立关系等),那就会轻则产生脏数据,重则导致系统错误。

因此,在当前普遍分布式服务的情况下,如何避免和解决重复请求给我们带来的数据异常成为了亟待解决的问题。而避免重复请求,最好的做法是前后端共同去做。

1. 前端或客户端在非幂等的按钮上直接做禁止提交重复请求的操作。

2. 后端在接收到请求时加锁,完成后解锁。

这篇博客主要讲的是在后端基于分布式锁的概念去出一个关于解决重复请求的通用解决方案。

二、正文

为何要使用分布式锁来解决呢?因为我们当前普遍的架构都是分布式的服务端,前端请求通过网关层转发至后端,如下图所示,因此如果只在一个单独的服务器上做限制,就无法在分布式的服务中完成应对高频次的重复请求了。

基本思路

思路基本上是对需要做防止重复请求的接口加上分布式锁,步骤如下:

  1. 在接收到请求后,根据方法名+参数取md5值,获取该方法及该参数的唯一标识;
  2. 获取标识后设置分布式锁,并且设置过期时间;
  3. 在请求结束后,释放分布式锁。

即可完成对当前请求的重复请求禁止。如果想做通用的解决方案,那就需要把上述步骤做出一个小功能出来,由于本人对java、spring框架比较熟悉,就拿这个来做个示例。

基于spring切面、redis的实现

想必一些熟悉spring的同学已经知道我想采用什么方式了,做通用型的,肯定要用到spring的aop特性,注解+切面+md5key+反射+redis实现,具体如下:

  1. 定义一个分布式锁注解,注解包含过期时间设置、忽略参数;
  2. 定义一个切面,切点为分布式锁注解,在切面中获取需要使用分布式锁的方法名、参数、过期时间,并且将方法名及未被忽略参数做md5取唯一标识;
  3. 再根据上述唯一标识设置redsis分布式锁;
  4. 方法结束后解锁。

代码如下:

注解

定义名称为RepeatOperationLock的注解,参数有锁过期时间及忽略属性(即不参与分布式锁标识MD5计算的属性)。

@Documented@Inherited@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})@Componentpublic @interface RepeatOperationLock { /** * 锁时长,默认500ms * @return */ long timeOut() default 500; /** * 忽略上锁参数位置,从0开始 * @return */ int[] ignoreIndex();}复制代码

切面

切点为上述注解,切面中做了以下几件事,获取方法名、获取注解属性(过期时间、忽略属性)、计算方法+属性的md5值、调用外部分布式锁的方法。

@Aspect@Slf4j@Componentpublic class LockAspect { @Autowired RepeatLockService repeatLockService; @Pointcut("@annotation(com.ls.javabase.aspect.annotation.RepeatOperationLock)") public void serviceAspect() { } @Before("serviceAspect()") public void setLock(JoinPoint point) { log.info("防止方法重复调用接口锁,上锁,point:{}

设置公共请求参数_基于分布式锁的防止重复请求解决方案(值得收藏)相关推荐

  1. 分布式锁的一些细节问题,值得收藏

    聊聊后端面试那些事 原文 分布式锁问题-[公粽号:堆栈future] 我看在技术大群里面有人问分布式锁问题,说是被面试官各种刁难,我是实在看不下去了,面试官意思很明确,你们有造火箭的经验吗,有的话来他 ...

  2. 【SpringBoot框架篇】31.基于分布式锁或xxx-job实现分布式任务调度

    文章目录 1.简介 2.分布式锁实现 2.1.引用依赖 2.2.定义分布式锁注解 2.3.配置切入点和获取锁释放锁逻辑 2.4.测试任务 3.使用分布式任务调度平台xxx-job 3.1.下载源码并运 ...

  3. 面试官让我设计一个基于分布式锁的库存超卖方案,并发量很高的那种

    今天给大家聊一个有意思的话题:每秒上千订单场景下,如何对分布式锁的并发能力进行优化? 背景引入 首先,我们一起来看看这个问题的背景? 前段时间有个朋友在外面面试,然后有一天找我聊说:有一个国内不错的电 ...

  4. 灵活运用分布式锁解决数据重复插入问题

    作者:快应用服务器研发团队-Lin Yupan 一.业务背景 许多面向用户的互联网业务都会在系统后端维护一份用户数据,快应用中心业务也同样做了这件事.快应用中心允许用户对快应用进行收藏,并在服务端记录 ...

  5. 分布式架构:并发重复请求和幂等场景技术实现总结

    分布式架构:并发重复请求和幂等场景技术实现总结 原文:分布式架构:并发重复请求和幂等场景技术实现总结 概念 重复请求是指一个请求因为某些原因被多次提交,场景简述如下: 1)用户快速多次点击按钮 2)N ...

  6. Java使用Redis实现分布式锁来防止重复提交问题

    如何用消息系统避免分布式事务? - 少年阿宾 - BlogJava http://www.blogjava.net/stevenjohn/archive/2018/01/04/433004.html ...

  7. java请求参数_在Java中发送http的post请求,设置请求参数等等

    前几天做了一个定时导入数据的接口,需要发送http请求,第一次做这种的需求,特地记一下子, 导包 import java.text.SimpleDateFormat; import java.util ...

  8. 一个项目部署多个节点会导致锁失效么_不为人知的分布式锁实现,全都在这里了

    1引入业务场景 首先来由一个场景引入: 最近老板接了一个大单子,允许在某终端设备安装我们的APP,终端设备厂商日活起码得几十万到百万级别,这个APP也是近期产品根据市场竞品分析设计出来的,几个小码农通 ...

  9. redis 分布式锁 看门狗_漫谈分布式锁之Redis实现

    笔耕墨耘,深研术道. 01写在前面Redis是一个高性能的内存数据库,常用于数据库.缓存和消息中间件.它提供了丰富的数据结构,更适合各种业务场景:基于AP模型,Redis保证了其高可用和高性能. 本文 ...

最新文章

  1. Hutool之集合工具——CollectionUtil
  2. Matlab与线性代数 -- 矩阵的乘法
  3. angularjs1访问子组件_vue 组件通信看这篇就够了(12种通信方式)
  4. python的des和3des加解密
  5. TCODE找相應的BAPI(主要是找到包PACKAGE)
  6. ThinkPHP 3.2.3 简单后台模块开发(一)常用配置
  7. android json转字符串数组,转换字符串到json数组出错
  8. HH SaaS电商系统的支付模块设计
  9. 多线程 调用 axis 报错_java笔记录(三、多线程)
  10. 抓包红色_抓包三部曲 WebSocket 协议原理抓包分析
  11. 2016级算法期末模拟练习赛-B.AlvinZH的青春记忆I
  12. 地方旅游产业运行监测与应急指挥平台/旅游资源管理平台/旅游产业监测平台/旅游应急指挥平台/旅游资源统计/旅游线路数据/旅游产业可视化大屏管理系统/餐饮场所数据/游客流量监测/景区数据监测/视频监控
  13. promise的理解和应用
  14. Java 中与()短路与()以及 或(|)短路或(||)的关系
  15. iOS shareExtension总结分享
  16. Daraz平台怎么样?Daraz平台哪些产品热销?Daraz如何批量上传产品快速铺货?
  17. RecyclerView实现广告轮播图(一)
  18. 测试之颠,必先利其器
  19. 流利阅读 2019.1.30 China’s Baidu pledges to improve search service after complaint
  20. 路由器上面的WAN口和LAN口是什么意思

热门文章

  1. 前端学习(2760):image基本使用
  2. 工作164:对父和混入的理解
  3. 工作47:继续理解父子组件
  4. 工作总结16:多看官网
  5. 前端学习(1942)vue之电商管理系统电商系统之创建商品分类的分支
  6. 前端学习(733):函数的参数
  7. 前端学习(705):do-while
  8. 前端学习(577):margin等其他属性扩展
  9. 第九十六期:JavaScript 中的 4 个相等比较算法的介绍
  10. html:(19):单选框,复选框,下拉列表框