幂等性问题的常见处理办法

ConstXiong

共 1056字,需浏览 3分钟

 · 2021-05-02

在计算机中的幂等操作是指任意多次执行产生的效果和一次执行的效果相同。


在以下场景中会遇到非幂等的情况:
  1. 前端重复提交同一表单,比如由于网络延迟用户多次点击提交按钮
  2. 恶意重复提交,比如绕过前端组件的限制,直接请求接口进行投票刷票
  3. 失败重试,比如 nginx 和 dubbo 的 retry
  4. 消息重复消费,比如消费方未确认消费、网络问题导致 MQ 未收到确认消费、消费方处理超时、MQ 收到确认消费但处理失败,都可能会重复发送消息


这时候就要加入幂等性处理:
  1. 前端表单提交之后,提交按钮 disable
  2. 使用 token 机制防止重复提交,客户端调用接口前先从后端申请 token,然后调用接口带上 token,第一次调用成功后端将 token 删除,若后续重复调用,后端校验 token 已删除,返回失败
  3. 在插入和删除场景,使用分布式 ID + 数据库主键或唯一索引的方式处理,重复插入相同 ID 的数据,数据库会抛出异常,Java 代码对异常进行处理
  4. 更新场景,使用数据库的乐观锁,表结构加上版本字段,version 不匹配不更新
    update t set field=?, version=version+1 where ID=? and version = ?;
  5. 带条件的数据库插入
    insert into t values(?, ?) where not exists (select id from t where id = ?)
  6. MQ 的幂等处理,客户端给消息生成全局唯一 msg-id,MQ 根据 msg-id 判断是否消息已投递;根据 msg-id 或业务相关的 biz-id,这里暂且记为 ID,业务端判断 ID 是否已处理,已处理丢弃即可。

上述第 2 点判断 token 是否删除、第 6 点判断消息是否已处理,都存在竞态条件,需要加入锁,至于是 JVM 级别的锁还是分布式锁,要看具体架构。

祝:假期愉快!
浏览 16
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报