【206期】面试官:你的项目是如何处理重复请求/并发请求的?

点击上方“Java面试题精选”,关注公众号

面试刷图,查缺补漏

>>号外:公众号改版后文章顺序不固定,欢迎大家把我们面试题精选这个公众号设置为星标,感谢大家一年的支持!!

阶段汇总集合:一年内容,200期Java面试题阶段汇总

对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,例如交易的接口如果重复请求可能会重复下单。

重复的场景有可能是:

  1. 黑客拦截了请求,重放

  2. 前端/客户端因为某些原因请求重复发送了,或者用户在很短的时间内重复点击了。

  3. 网关重发

  4. ….

本文讨论的是如何在服务端优雅地统一处理这种情况,如何禁止用户重复点击等客户端操作不在本文的讨论范畴。

利用唯一请求编号去重

你可能会想到的是,只要请求有唯一的请求编号,那么就能借用Redis做这个去重——只要这个唯一请求编号在redis存在,证明处理过,那么就认为是重复的

代码大概如下:

String userId= "12345678";//用户
String method = "pay";//接口名
String dedupMD5 = new ReqDedupHelper().dedupParamMD5(req,"requestTime");//计算请求参数摘要,其中剔除里面请求时间的干扰
String KEY = "dedup:U=" + userId + "M=" + method + "P=" + dedupMD5;

long expireTime =  1000;// 1000毫秒过期,1000ms内的重复请求会认为重复
long expireAt = System.currentTimeMillis() + expireTime;
String val = "expireAt@" + expireAt;

// NOTE:直接SETNX不支持带过期时间,所以设置+过期不是原子操作,极端情况下可能设置了就不过期了,后面相同请求可能会误以为需要去重,所以这里使用底层API,保证SETNX+过期时间是原子操作
Boolean firstSet = stringRedisTemplate.execute((RedisCallback<Boolean>) connection -> connection.set(KEY.getBytes(), val.getBytes(), Expiration.milliseconds(expireTime),
        RedisStringCommands.SetOption.SET_IF_ABSENT));

final boolean isConsiderDup;
if (firstSet != null && firstSet) {
    isConsiderDup = false;
else {
    isConsiderDup = true;
}

END

来源:jaskey.github.io/blog/2020/05/19/handle-duplicate-request

十期推荐

【191期】面试官:你能说说SOA架构和微服务架构的区别嘛?

【192期】面试官:线程池中多余的线程是如何回收的?

【193期】如何利用装饰者模式在不改变原有对象的基础上扩展功能

【194期】Redis——第三方jar没有封装的命令我们该怎么执行?

【195期】MySQL中的条件判断函数 CASE WHEN、IF、IFNULL你会用吗?

【196期】夯实基础,Java8新特性Stream详细教程

【197期】华为OD两轮技术面试记录,给后来人一个参考!

【198期】面试官:你能说出 方法重载和方法重写 的原理吗?

【199期】100%会用到的hashCode()和equals()方法及使用规范,你掌握了吗?

【200期】面试官:你能简单说说 SpringMVC 的执行原理吗?


与其在网上拼命找题? 不如马上关注我们~

【206期】面试官:你的项目是如何处理重复请求/并发请求的?

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/7683.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!