在日常开发中,咱们常常会面对防止重复请求的问题。当服务端对于请求的响应涉及数据的修改,或状态的变动时,可能会形成极大的危害。重复请求的后果在交易系统、售后维权,以及支付系统中尤为严重。可是不少时候,都是期望着前端来限制,好比提交以后,按钮diseabled之类的,其实这些都是不靠谱的。关键时候仍是须要后端来校验。前端
Redis存储查询轻量快速。在request进来的时候,能够先记录在缓存中。后续进来的request每次进行验证。整个流程处理完成,清除缓存。redis
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();
须要原子性操做,想到了数据库的惟一索引。新建一个表,每次request进来则往表里面插入数据, 操做完成后,删除此条记录。shell
因为数据库的操做比较消耗性能,了解到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