#防重复处理总结
##背景
在业务开发中,我们常会面对防止重复请求的问题。当服务端对于请求的响应涉及数据的修改,或状态的变更时,可能会造成极大的危害。重复请求的后果在交易系统、售后维权,以及支付系统中尤其严重。
前台操作的抖动,快速操作,网络通信或者后端响应慢,都会增加后端重复处理的概率。
前台操作去抖动和防快速操作的措施,我们首先会想到在前端做一层控制。当前端触发操作时,或弹出确认界面,或disable入口并倒计时等等,此处不细表。
但前端的限制仅能解决少部分问题,且不够彻底,后端自有的防重复处理措施必不可少,义不容辞。
在接口实现中,我们常要求接口要满足幂等性,来保证多次重复请求时只有一次有效。
查询类的接口几乎总是幂等的,但在包含诸如数据插入,多模块数据更新时,达到幂等性会比较难,尤其是高并发时的幂等性要求。比如第三方支付前台回调和后台回调,第三方支付批量回调,慢性能业务逻辑(如用户提交退款申请,商家同意退货/退款等)或慢网络环境时,是重复处理的高发场景。
##尝试
这里针对“用户提交退款申请”的例子,说明一下尝试过的防重复处理方法的效果。
后端防重复处理的方式,我们先后尝试了三种:
####1)基于DB中退款订单状态的验证
这种方式简单直观,从DB查询出来的退款详情(包括状态)往往还可以用在后续逻辑中,没有花额外的工作专门应对重复请求的问题。
这种查询状态后进行验证的逻辑,从代码上线后就一直存在于所有含状态的业务逻辑处理中,必不可少。但对于防重复处理效果并不好:在前端添加防重复提交前,每周平均在25笔;前端优化后,每周降到7笔。这个数量占总退款申请数的3%%,一个仍然无法接受的比例。
理论上,任意次请求只要在数据状态更新之前都完成了查询操作,则业务逻辑的重复处理就会发生。如下图所示。优化的方向是减少查询到更新之间业务处理时间,可降低空档期的并发影响。极致情况下如果查询和更新变成了原子操作,则就不存在我们当前的问题。
####2)基于缓存数据状态的验证
Redis存储查询轻量快速。在request进来的时候,可以先记录在缓存中。后续进来的request每次进行验证。整个流程处理完成,清除缓存。以退款为例子:
I. 每次退款发起申请,读取缓存中是否有以orderId为key的值
II. 没有,则往缓存中写入以orderId为key的value
III.有,则说明有该订单的退款正在进行。
IV. 操作完清缓存,或者缓存存值的时候设置生命周期
与1)的发放相比,数据库换成响应更快的缓存。但是仍然不是原子操作。插入和读取缓存还是有时间间隔。在极致的情况下还是存在重复操作的情况。
此方法优化后,每周1笔重复操作。
####3)利用唯一索引机制的验证
需要原子性操作,想到了数据库的唯一索引。
新建一个TradeLock表:
CREATE TABLE `TradeLock` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`type` int(11) NOT NULL COMMENT '锁类型',
`lockId` int(11) NOT NULL DEFAULT '0' COMMENT '业务ID',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '锁状态',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Trade锁机制';
每次request进来则往表里面插入数据:
——成功,则可以继续操作(相当于获取锁);
——失败,则说明有操作在进行。
操作完成后,删除此条记录。(相当于释放锁)
目前已经上线,等待下周的数据统计。
####4)基于缓存的计数器验证:
由于数据库的操作比较消耗性能,了解到redis的计数器也是原子性操作。果断采用计数器。既可以提高性能,还不用存储,而且能提升qps的峰值。
还是以订单退款为例子:
每次request进来则新建一个以orderId为key的计数器,然后+1。
如果>1(不能获得锁): 说明有操作在进行,删除。
如果=1(获得锁): 可以操作。
操作结束(删除锁):删除这个计数器。
要了解计数器,可以参考:
##总结:
PHP语言自身没有提供进程互斥和锁定机制。因此才有了我们上面的尝试。
网上也有文件锁机制,但是考虑到我们的分布式部署,建议还是用缓存。
在大并发的情况下,程序各种情况的发生。特别是涉及到金额操作,不能有一分一毫的差距。所以在大并发要互斥的情况下可以考虑3、4两种方案。
爱迪生尝试了1600多种材料选择了钨丝发明了灯泡,实践出真知。遇到问题,和问题斗争,最后解决问题是一个最大提升自我的过程,不但加宽自己的知识广度,更加深了自己的技能深度。达到目标之后的成就感更是不言而喻。
- 作者:蘑菇街商家平台资金团队工程师 @木照
相关推荐
本案例源代码是Lux_Sun在CSDN博客上分享的一个关于防止重复登录的实践教程。 首先,我们要理解防止重复登录的基本原理。通常,当用户成功登录后,服务器会返回一个会话ID(Session ID)给客户端,客户端将这个ID...
4. 并发控制:在高并发环境下,防止重复登录的策略必须能够高效地处理大量请求,避免性能瓶颈。 5. 防止误判:确保策略不会误判正常的行为,如用户在切换网络环境或设备后重新登录。 四、技术选型与框架支持 许多...
它支持多种数据结构如字符串、哈希、列表、集合和有序集合,这使得它非常适合用于存储临时性的、需要快速访问的数据,比如用于防止重复提交的令牌。 现在,我们将Spring AOP引入进来。AOP是面向切面编程,允许...
总结,防止重复提交是Web开发中的关键实践,Struts2提供了Token机制作为主要手段。理解并正确实现这些机制,能够确保应用的稳定性和数据的完整性。同时,结合其他防御措施,如Session检查、请求方法限制和数据库事务...
这样,就可以避免重复请求带来的问题。 在上述文档中,作者首先声明了一个pending数组,用于存储每个请求的取消函数和axios标识。然后通过axios拦截器,在请求发送前和响应后对pending数组进行检查和处理。在请求...
### Struts2防止重复提交的解决方案 #### 一、引言 在Web应用程序开发中,一个常见的问题是如何有效地防止表单的重复提交。这不仅能够提高用户体验,还能增强系统的安全性。Struts2作为一款广泛使用的Java Web应用...
3. 使用Struts2的拦截器处理登录逻辑,如Session管理,防止重复登录等。 三、参数请求处理 Struts2通过OGNL(Object-Graph Navigation Language)表达式语言,方便地获取和设置HTTP请求参数。Action类中的方法可以...
通过这些知识点,我们可以总结出天鹅到家支付系统高可用架构设计的核心在于构建一个既能够处理高并发支付请求、又能保证数据一致性和系统稳定性的高效体系。这一架构通过引入了幂等性、分布式锁、TCC事务模式、MVCC...
### AJAX设计模式与最佳实践 #### 一、引言 AJAX(Asynchronous JavaScript and XML)是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新。这意味着可以在不重新...
9. **最佳实践**:总结在网络游戏运营中防止和处理重复IP地址的最佳实践,以供业界参考。 这个文档对于网络游戏开发者、网络管理员以及对网络技术感兴趣的个人来说,都是一份宝贵的资源,它可以帮助他们理解和应对...
在客户端限制表单重复提交是Web开发中一个重要的实践,主要目的是防止用户意外或恶意地多次提交同一份数据,导致数据库出现重复记录或者系统逻辑出错。本文将详细阐述两种客户端限制表单重复提交的方法,并结合...
- Struts框架中防止表单重复提交的方法及其版本差异 - Map遍历方式及ArrayList与LinkedList的应用场景 - Redirect与Forward的区别及其对request参数的影响 - JSP中默认的会话作用域 - Spring事务管理与AOP的...
### 面向SPA与Hybrid应用的前端工程体系与实践经验 #### 一、概述 在当前快速发展的互联网行业中,单页应用(SPA, Single Page Application)与混合应用(Hybrid App)成为移动互联网时代的重要组成部分。这两种应用...
总结,"ExtJs4.0 表单提交Demo"旨在展示如何在ExtJs 4.0环境中优雅地处理表单数据提交,同时遵循良好的软件设计原则,将显示层和控制层分离。通过理解和实践这个Demo,开发者能够更好地掌握ExtJs 4.0的表单和Ajax...
4. **ActionMapping**:定义了Action与URL的映射关系,决定特定请求应调用哪个Action。 5. **Tiles**:Struts的视图管理组件,允许将页面分解为可复用的组件,便于构建复杂的布局。 6. **Struts配置文件**:struts...
在PHP开发中,防止页面重复提交是一个非常重要的实践,它能确保数据的准确性和一致性,尤其是在处理关键操作如支付、用户注册或数据修改时。以下是对三种防重复提交方法的详细解释: 1. 提交按钮置disabled 这种...
4. **避免冗余**:利用Connect的中间件特性,避免重复编写处理相同逻辑的代码。 5. **使用路由参数验证**:对动态路由参数进行验证,防止无效的数据输入。 最后,文件名为`myRouter`的可能是一个包含自定义路由器...
总结来说,全民K歌歌房技术实践涵盖了音视频处理、网络抗性增强、稳定性保障、异常处理和创新功能实现等多个关键领域,展现了在构建复杂在线互动服务时所需的技术深度和创新能力。这些实践对于理解在线音视频互动...
5. 幂等性设计:每个请求唯一标识,确保同一请求只被处理一次,防止重复秒杀。 五、系统实现 1. 商品接口设计:提供获取商品信息、参与秒杀等接口,采用RESTful风格,便于前后端分离。 2. 用户认证:使用JWT生成并...
- **脚本去重**:移除重复的脚本,防止IE浏览器发起多次HTTP请求,优化加载效率。 #### 三、总结 Web2.0网站性能优化是一项综合性工作,涉及DNS解析、减少请求、页面布局、静态资源处理、Cookie管理、多域名服务、...