文档章节

蘑菇街防重复请求处理的实践与总结

霖vv
 霖vv
发布于 2016/10/01 20:37
字数 1486
阅读 1.3K
收藏 0

阿里云携手百名商业领袖、技术大咖,带您一探行进中的数字新基建!>>>

#防重复处理总结
##背景
在业务开发中,我们常会面对防止重复请求的问题。当服务端对于请求的响应涉及数据的修改,或状态的变更时,可能会造成极大的危害。重复请求的后果在交易系统、售后维权,以及支付系统中尤其严重。

前台操作的抖动,快速操作,网络通信或者后端响应慢,都会增加后端重复处理的概率。

前台操作去抖动和防快速操作的措施,我们首先会想到在前端做一层控制。当前端触发操作时,或弹出确认界面,或disable入口并倒计时等等,此处不细表。

但前端的限制仅能解决少部分问题,且不够彻底,后端自有的防重复处理措施必不可少,义不容辞。

在接口实现中,我们常要求接口要满足幂等性,来保证多次重复请求时只有一次有效。

查询类的接口几乎总是幂等的,但在包含诸如数据插入,多模块数据更新时,达到幂等性会比较难,尤其是高并发时的幂等性要求。比如第三方支付前台回调和后台回调,第三方支付批量回调,慢性能业务逻辑(如用户提交退款申请,商家同意退货/退款等)或慢网络环境时,是重复处理的高发场景。

##尝试

这里针对“用户提交退款申请”的例子,说明一下尝试过的防重复处理方法的效果。

后端防重复处理的方式,我们先后尝试了三种:

####1)基于DB中退款订单状态的验证

这种方式简单直观,从DB查询出来的退款详情(包括状态)往往还可以用在后续逻辑中,没有花额外的工作专门应对重复请求的问题。

这种查询状态后进行验证的逻辑,从代码上线后就一直存在于所有含状态的业务逻辑处理中,必不可少。但对于防重复处理效果并不好:在前端添加防重复提交前,每周平均在25笔;前端优化后,每周降到7笔。这个数量占总退款申请数的3%%,一个仍然无法接受的比例。

理论上,任意次请求只要在数据状态更新之前都完成了查询操作,则业务逻辑的重复处理就会发生。如下图所示。优化的方向是减少查询到更新之间业务处理时间,可降低空档期的并发影响。极致情况下如果查询和更新变成了原子操作,则就不存在我们当前的问题。

image

####2)基于缓存数据状态的验证
Redis存储查询轻量快速。在request进来的时候,可以先记录在缓存中。后续进来的request每次进行验证。整个流程处理完成,清除缓存。以退款为例子:

    I.  每次退款发起申请,读取缓存中是否有以orderId为key的值
    II. 没有,则往缓存中写入以orderId为key的value
    III.有,则说明有该订单的退款正在进行。
    IV. 操作完清缓存,或者缓存存值的时候设置生命周期

与1)的发放相比,数据库换成响应更快的缓存。但是仍然不是原子操作。插入和读取缓存还是有时间间隔。在极致的情况下还是存在重复操作的情况。
此方法优化后,每周1笔重复操作。

image

####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进来则往表里面插入数据:

——成功,则可以继续操作(相当于获取锁);
——失败,则说明有操作在进行。

操作完成后,删除此条记录。(相当于释放锁)
目前已经上线,等待下周的数据统计。

image

####4)基于缓存的计数器验证:

由于数据库的操作比较消耗性能,了解到redis的计数器也是原子性操作。果断采用计数器。既可以提高性能,还不用存储,而且能提升qps的峰值。

还是以订单退款为例子:

每次request进来则新建一个以orderId为key的计数器,然后+1。

如果>1(不能获得锁): 说明有操作在进行,删除。

如果=1(获得锁): 可以操作。

操作结束(删除锁):删除这个计数器。
要了解计数器,可以参考:

link

image

##总结:

PHP语言自身没有提供进程互斥和锁定机制。因此才有了我们上面的尝试。

网上也有文件锁机制,但是考虑到我们的分布式部署,建议还是用缓存。

在大并发的情况下,程序各种情况的发生。特别是涉及到金额操作,不能有一分一毫的差距。所以在大并发要互斥的情况下可以考虑3、4两种方案。

爱迪生尝试了1600多种材料选择了钨丝发明了灯泡,实践出真知。遇到问题,和问题斗争,最后解决问题是一个最大提升自我的过程,不但加宽自己的知识广度,更加深了自己的技能深度。达到目标之后的成就感更是不言而喻。

本文转载自:http://mogu.io/prevent-duplicate-requests-4

下一篇: 幂等性
霖vv

霖vv

粉丝 24
博文 192
码字总数 118259
作品 0
朝阳
程序员
私信 提问
加载中

评论(0)

2019年微服务实践第一课,网易&谐云&蘑菇街&奥思技术大咖深度分享

微服务的概念最早由Martin Fowler与James Lewis于2014年共同提出,核心思想是围绕业务能力组织服务,各个微服务可被独立部署,服务间是松耦合的关系,以及数据和治理的去中心化管理。微服务能...

网易云
2019/01/08
0
0
0到1再到100 蘑菇街搜索与推荐架构的探索之路

丁小明,花名小宝,蘑菇街搜索技术团队负责人。2011年底加入蘑菇街,2013年开始负责搜索团队,见证了蘑菇街一路蓬勃发展的历程,也和团队一起从零起步摸爬滚打,打造了蘑菇街的搜索推荐体系,...

雪夜凋零
2017/07/28
0
0
七牛架构师实践日-第十四期-移动直播技术最佳实践

七牛架构师实践日-第十四期-移动直播技术最佳实践 2016 直播元年 智能,互动,实时成为了未来的趋势 低门槛和灵活性让直播的浪潮似乎愈加汹涌 卡顿、延迟现象 依旧是直播产品的痛点 如何将技...

七牛云
2016/09/29
12
0
七牛架构师实践日-第十四期-移动直播技术最佳实践

七牛架构师实践日-第十四期-移动直播技术最佳实践 2016 直播元年 智能,互动,实时成为了未来的趋势 低门槛和灵活性让直播的浪潮似乎愈加汹涌 卡顿、延迟现象 依旧是直播产品的痛点 如何将技...

七牛云
2016/09/29
66
0
开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀

1、前言 随着云IM的发展,已吸引越来越多有IM需求的APP接入。但考虑到云IM无论从商业模式还是运营模式上,还需经过多年的沉淀,才可能真正实现客户与服务商的运营和服务良性循环的双赢局面。...

JackJiang-
2016/07/28
3.2K
4

没有更多内容

加载失败,请刷新页面

加载更多

URL 中文链接 编码错误 完美解决

直接上代码 str = "%25E4%25B8%25AD%25E6%2596%2587";console.log(str);str =decodeURIComponent(decodeURIComponent(str));console.log(str); 输出结果 %25E4%25B8%25AD%25E6%2596%25......

放只虎归个山
38分钟前
17
0
.NET中小数,浮点数和双精度之间的区别? - Difference between decimal, float and double in .NET?

问题: What is the difference between decimal , float and double in .NET? .NET中的decimal , float和double float什么区别? When would someone use one of these? 有人什么时候会使用......

fyin1314
今天
22
0
如何找出Windows上正在侦听端口的进程? - How can you find out which process is listening on a port on Windows?

问题: 如何找出Windows上正在侦听端口的进程? 解决方案: 参考一: https://stackoom.com/question/CXO/如何找出Windows上正在侦听端口的进程 参考二: https://oldbug.net/q/CXO/How-can...

技术盛宴
今天
10
0
OSChina 周三乱弹 —— 一家动物都快饿成标本了~

@黑觉非常君 :前天晚上9点开始睡觉,睡到昨天上午8点起床,昨天下午2点又睡,睡到下午7点多,晚上10点又困了,又睡,睡到今天上午8点,中途没醒过,怎么这么能睡,是不是快挂了。 能睡不是好...

小小编辑
今天
24
0
神剧推荐全剧最污片段精剪

神剧推荐,全剧最污片段精剪 豆瓣评分最高,脑洞最大,脑回路最曲折,恶搞无数经典,没有一条差评的神剧 整个系列完整版 到这里观看

a57571735
今天
22
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部