本文转载自微信公众号「UP技术控」,作者 conan5566。转载本文请联系UP技术控公众号。 conan5566
成都创新互联公司作为成都网站建设公司,专注重庆网站建设公司、网站设计,有关成都定制网站方案、改版、费用等问题,行业涉及岗亭等多个领域,已为上千家企业服务,得到了客户的尊重与认可。
背景
在平常开发中,我们经常会面对防止重复请求的问题。当服务端对于请求的响应涉及数据的修改,或状态的变更时,可能会造成极大的危害。重复请求的后果在交易系统、售后维权,以及支付系统中尤其严重。但是很多时候,都是指望着前端来限制,比如提交之后,按钮diseabled之类的,其实这些都是不靠谱的。关键时候还是需要后端来校验。
解决方式
1、基于缓存数据状态的验证
Redis存储查询轻量快速。在request进来的时候,可以先记录在缓存中。后续进来的request每次进行验证。整个流程处理完成,清除缓存。
- if (!CacheExtension.getInstance().AddUnique($"{key}_unique", 1, DateTimeOffset.Now.AddDays(365)))
- {
- LogExtention.getInstance().WriteCustomLogAsync("", "", true, "上批次还未执行结束");
- return ResponseResult.FromError("上批次还未执行结束!");
- }
- if (!string.IsNullOrEmpty(uniqueKey))
- {
- CacheExtension.getInstance().Remove(uniqueKey);
- }
- return ResponseResult.Ok();
2、利用唯一索引机制的验证
需要原子性操作,想到了数据库的唯一索引。新建一个表,每次request进来则往表里面插入数据, 操作完成后,删除此条记录。
3、基于缓存的计数器验证
由于数据库的操作比较消耗性能,了解到redis的计数器也是原子性操作。果断采用计数器。既可以提高性能,还不用存储,而且能提升qps的峰值。 每次request进来则新建一个以orderId为key的计数器,然后+1。如果>1(不能获得锁): 说明有操作在进行,删除。如果=1(获得锁): 可以操作。
- redis> SET test 20
- OK
- redis> INCR test
- (integer) 21
- redis> GET test # 数字值在 Redis 中以字符串的形式保存
- "21"
- //获取指定的所有计数器
- HGETALL counter:user:{userID}
- //获取指定的指定计数器
- HMGET counter:user:{userID} praiseCnt hostCnt
- //指定点赞数+1
- HINCRBY counter:user:{userID} praiseCnt
总结
1、c#本身有lock机制,单体模式可以使用。
2、但是考虑到我们的分布式部署,建议还是用缓存。在大并发的情况下,程序各种情况的发生。特别是涉及到金额操作。所以在大并发要互斥的情况下可以考虑2、3两种方案。
分享标题:面试官扎心一问:防止重复请求提交,有什么方案?
本文来源:http://www.gawzjz.com/qtweb2/news15/1065.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联