当前位置: 首页 > 科技观察

面试官问:有什么方案防止提交重复请求?

时间:2023-03-22 00:46:05 科技观察

本文转载自微信公众号《UP技控》,作者conan5566。转载本文请联系UP技控公众号。conan5566背景在平时的开发中,我们经常会遇到防止重复请求的问题。当服务器对请求的响应涉及数据修改或状态改变时,可能会造成很大的危害。重复请求的后果在交易系统、售后维权、支付系统中尤为严重。但是很多时候是靠前端来限制,比如提交之后,按钮被禁用等等,其实这些都是不靠谱的。关键时候还是需要后台进行验证。方案一、基于缓存数据状态的校验,Redis存储查询轻量快速。当请求进来的时候,可以先记录在缓存中。每次都会验证后续传入的请求。整个过程处理完毕,缓存清空。if(!CacheExtension.getInstance().AddUnique($"{key}_unique",1,DateTimeOffset.Now.AddDays(365))){LogExtention.getInstance().WriteCustomLogAsync("","",true,"on该批次尚未执行");returnResponseResult.FromError("最后一批还没有执行!");}if(!string.IsNullOrEmpty(uniqueKey)){CacheExtension.getInstance().Remove(uniqueKey);}returnResponseResult.Ok();2.使用唯一索引机制的校验需要原子操作,想到了数据库的唯一索引。新建一个表,每次有请求进来就往表中插入数据,操作完成后删除这条记录。3、基于缓存的计数器校验由于数据库操作比较消耗性能,了解到redis计数器也是原子操作。果断使用计数器。它可以在不需要存储的情况下提高性能,并且可以提高qps的峰值。每次有请求进来,新建一个计数器,以orderId为key,然后+1。If>1(unabletoacquirelock):说明有操作正在进行,删除。if=1(获得锁):可以操作。redis>SETtest20OKredis>INCRtest(integer)21redis>GETtest#NumbervalueisstoredinRedisasastring"21"//获取所有指定的计数器HGETALLcounter:user:{userID}//获取指定的指定计数器HMGETcounter:user:{userID}praiseCnthostCnt//指定点赞数+1HINCRBYcounter:user:{userID}praiseCnt总结1、C#本身有锁机制,可以使用single模式。2.但是考虑到我们的分布式部署,还是建议使用缓存。在大并发的情况下,会出现程序的各种情况。特别是涉及到金额操作时。所以在大并发互斥的情况下可以考虑2和3两种方案。