美文网首页面试我爱编程maven
防重复请求处理方案

防重复请求处理方案

作者: wyatt_plus | 来源:发表于2018-06-20 16:12 被阅读202次

    1. 背景

    在业务开发中,我们常会面对防止重复请求的问题。当服务端对于请求的响应涉及数据的修改,或状态的变更时,可能会造成极大的危害。重复请求的后果在交易系统、售后维权,以及支付系统中尤其严重。
    前台操作的抖动,快速操作,网络通信或者后端响应慢,都会增加后端重复处理的概率。
    前台操作去抖动和防快速操作的措施,我们首先会想到在前端做一层控制。当前端触发操作时,或弹出确认界面,或disable入口并倒计时等等。

    2. 问题

    虽然前端的限制仅能解决少部分问题,且不够彻底,后端自有的防重复处理措施必不可少,义不容辞。
    在接口实现中,我们常要求接口要满足幂等性,来保证多次重复请求时只有一次有效。
    查询类的接口几乎总是幂等的,但在包含诸如数据插入,多模块数据更新时,达到幂等性会比较难,尤其是高并发时的幂等性要求。比如第三方支付前台回调和后台回调,第三方支付批量回调,慢性能业务逻辑(如用户提交退款申请,商家同意退货/退款等)或慢网络环境时,是重复处理的高发场景。

    3. 方案

    3.1 利用唯一索引机制的验证

    需要原子性操作,想到了数据库的唯一索引。
    新建一个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进来则往表里面插入数据:

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

    操作完成后,删除此条记录。(相当于释放锁)


    利用唯一索引

    3.2 基于缓存的计数器验证

    由于数据库的操作比较消耗性能,了解到redis的计数器也是原子性操作。果断采用计数器。既可以提高性能,还不用存储,而且能提升qps的峰值。
    以操作订单为例子:
    每次request进来则新建一个以orderId为key的计数器,然后+1。

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

    操作结束(删除锁):删除这个计数器。


    基于缓存的计数器验证

    4. 总结

    接口的防重复方案很多,但是出现的情况也很多。所以必须每个细节都做好把控,从前端到后端,每个节点都要到位,一定要符合接口的幂等性原则。

    相关文章

      网友评论

        本文标题:防重复请求处理方案

        本文链接:https://www.haomeiwen.com/subject/iksxyftx.html