5

接口幂等性详解 - 低吟不作语

 7 months ago
source link: https://www.cnblogs.com/Yee-Q/p/18012149
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

所谓接口幂等性就是:在特定场景下,同一条件的多次接口调用,保证操作只执行一次,如果接口没有保证幂等性,在以下场景就会产生问题

  • 前端重复提交:用户进行注册、创建个人信息等操作,由于网络抖动导致页面没有及时响应,用户认为没有成功而多次点击提交按钮,发生重复提交表单请求
  • 接口超时重试:提供外部系统调用的接口,因为网络抖动等原因执行成功但没能及时响应,外部系统发起重试,导致重复调用
  • 消息重复消费:使用消息中间件时,消费者手动 ack 确认消息被正常消费时,消费者突然断开连接,已经执行的消息会重新放回队列,被其他消费者重新消费

如何实现接口幂等性?

1. 防重 Token 令牌

具体流程如下:

  • 客户端获取 token,服务端将 token 保存在 redis 中,token 需保证全局唯一
  • 之后客户端发起请求时必须携带 token
  • 服务端校验 token,如果成功则执行业务,并删除 redis 中的 token,否则为重复操作,直接返回结果

这种方式需保证同一请求都携带同一 token,比如同一订单的支付操作都使用同一 token 请求。另外,在并发情况下,Redis 查找数据与删除需要保证原子性,可以使用或 Lua 脚本保证

2. 使用 Redis 实现

这种实现方式是基于 redis 的 setnx 命令实现的,作用是如果 key 不存在,将 key 赋值为 value 并返回 1,若 key 已存在,则不做操作并返回 0

具体流程如下:

  • 客户端请求服务端,将能代表这次请求的唯一标识以 setnx 的方式存入 redis,并根据业务设置相应的超时时间
  • 如果设置成功,代表是第一次请求,执行后续业务逻辑
  • 如果设置失败,代表已经执行过请求,直接返回

redis 是单线程的,所以不会有并发问题

3. 加锁实现

具体流程如下:

  • 客户端请求服务端,对能代表这次请求的唯一标识加锁,保证同一时刻同一请求只有一个能被执行
  • 服务端根据唯一标识判断是否第一次请求,比如查询数据库是否已存在该唯一标识的记录,或者该唯一标识对应记录状态是否为【已完成】
  • 如果是第一次请求,执行后续业务逻辑,否则直接返回

4. 幂等表

加锁会影响性能,我们可以建一张幂等表,为能代表这次请求的唯一标识建立唯一约束

具体流程如下:

  • 客户端请求服务端,服务端会将本次请求的信息插入幂等表
  • 因为有唯一约束,如果幂等表中不存在本次请求记录,则插入成功,执行后续业务逻辑,插入失败,则直接返回

使用这种方式,每次请求都会幂等表新建一条记录,为了避免表数据过大,可以定期进行清理,或者使用流水表来代替幂等表。使用插入而不是查询,也能有效避免并发问题


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK