ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Spring Boot接口防抖:基于AOP+Redis的防重复提交利器

Spring Boot接口防抖:基于AOP+Redis的防重复提交利器 先讲一个真实的翻车现场去年我负责的电商项目上线用户在结算页双击了“提交订单”后端下单接口在不到300毫秒内收到两次完全相同的请求结果生成了两笔订单财务对账立刻告警。当时第一反应是查前端代码——按钮明明已经做了disabled处理可问题出在网络层重试请求在极端情况下还是会漏进来。也就是从那次之后我开始认真研究SpringBoot接口防抖并且把它做成了一个通用能力沉淀在项目里。这篇内容写给所有正在用SpringBoot做接口开发的同行。不管你是写订单、支付、短信这类强交互接口还是做表单提交、扫码回调只要你不想因为用户连点、网络重试、脚本刷请求而背事故这篇文章都值得看完。我会从防抖到底挡什么、选型怎么选到注解AOPRedis的完整落地再到线上跑起来之后踩过的坑一次性讲透。1. 重复请求为何防不胜防先说清防抖到底在挡什么1.1 前端的防抖和后端的防抖压根不是一回事很多人一听“防抖”第一反应是前端已经用lodash的debounce做了为什么后端还要重复造轮子这里有个认知偏差前端的防抖防的是用户在页面上的连续操作比如疯狂点击提交按钮、快速滑动滑块。它的手段是“延迟最后一次执行”或者“在等待时间内忽略新事件”。但后端的接口风险主要来自前端控制不了的地方。举几个我实际遇到的场景浏览器网络重试弱网环境下客户端和网关之间的TCP连接断开客户端会静默重发请求而网关可能已经把第一个请求转发到了后端。网关或RPC框架的重试机制Spring Cloud微服务之间调用如果配置了Retry某个节点超时后会自动重试消费方会收到多个请求。恶意脚本和爬虫自动化工具直接绕过页面往接口上并发POST前端防抖完全失效。移动端SDK自动重连App在冷启动或切后台时某些网络库会自动补发未确认的请求。这些场景都指向同一个结论接口是否需要做防抖不能以“前端有没有做限制”为标准而应该假设“任何请求都不可信”。后端防抖的本质是在服务端建立一个时间窗口窗口内同一个业务请求只允许被实际处理一次。1.2 重复请求的严重后果不是“多跑一次代码”这么简单很多人觉得重复请求最多就是浪费点CPU顶多数据多一条。实际上我从生产事故里总结出的后果远比这个严重业务场景重复请求带来的后果严重程度提交订单生成多笔订单、重复扣款直接资金损失发送短信验证码用户被狂轰滥炸短信费用翻倍资金损失投诉注册/领取优惠券一个用户领到多张券活动超发营销活动失控库存扣减库存超卖订单无法履约违约赔付第三方回调通知支付结果重复入库、重复对账数据混乱就拿短信验证码来说我一个朋友的项目因为没有做接口防抖被一个脚本对着发送接口刷了一晚上第二天短信账单直接多了几万块。这个场景严格说起来既要防抖也要限流但防抖至少能把“同一个手机号在几秒内只能发一次”这个底线守住。1.3 防抖、幂等、限流这三个概念千万别混做防抖之前必须先把边界搞清楚否则代码写出来四不像。我见过不少团队把这三个东西混在一起做最后效果都不好。接口防抖针对“同一业务标识 时间窗口”的重复请求拦截。比如同一个用户ID在3秒内只能提交一次订单。它解决的是“短时间内重复提交”问题。幂等针对“同一业务唯一键”的结果去重。比如同一个订单号重复上报后台只处理一次。它解决的是“请求重复但业务结果只能有一个”的问题通常是永久性的。限流针对“接口整体调用频率”的控制。比如一个接口每秒最多承受100次请求。它解决的是“并发超过容量”问题通常按IP、用户或接口维度统计。防抖是三者里最轻量、最好落地的一种。它不要求数据库唯一键也不引入令牌桶算法核心就是“Redis里放一个带过期时间的key谁先写进去谁去处理”。2. 方案选型过滤器、拦截器、AOP我最终选了谁2.1 三种常用路线的横向对比当时我在项目里评估过三个方案Servlet过滤器、SpringMVC拦截器、Spring AOP切面。先说结论我最终选了AOP但并不是说另外两种一无是处而是它们各自适
返回列表