乐观锁实现接口幂等性_支持API幂等操作

背景

平台有部分 API 需要保证接口幂等性, 防止业务频繁刷 API 造成资源浪费,或者不小心重发消息影响业务。

名词解释

接口的幂等, 指的是一个操作重复执行N次得到的结果(副作用)与执行一次是相等的。比如在 HTTP 协议中,GET请求,会得到同样的数据。但是对于 POST 和 PATCH 的接口, 每次请求动作得到结果都是不同, 这里是不幂等的, 而有的是时候对接口有幂等的要求。

比如银行的转账, 由于各种原因可能同一个请求会被多次发送,但是结果只会成功转账一次,其他转账不会生效。

解决方案

目前业界有相对成熟的解决方案, 包括 悲观锁,乐观锁,防重表和使用 Token。下面分别介绍以上4种解决方案。

悲观锁

流程:请求过来的时候开启事务, 对查询事件(比如订单)加锁

判断事件是否符合执行条件

在全部执行完后, 提交或回滚

缺点: 执行时间长, 悲观锁容易锁住整表,导致服务不可用问题。

乐观锁

实现:通过版本号的方式,在更新事件的时候锁表 (大部分时间不会锁表), 比如:UPDATE table set usage=usage+1, version=version+1 where uuid = XXX and version = XXX

即使多个请求过来, 因为进来的 version 是相同的, 但是 DB 中的版本号已经被更新, 修改条件不成立, 也就是说不会被多次更新。

缺点: 使用 主键 或 唯一索引 来更新, 使用行锁而不是表锁。

防重表

流程:建立一张防重表, 使用事件 ID (比如订单号) 作为唯一索引

在发起请求时根据事件 ID 在 防重表 中新增一条记录

因为是唯一索引,重发的请求添加记录不会成功, 第一个进入的事件可以被执行(事件完成后,可以删除防重表的记录)

缺点:多维护一张数据表,增加业务逻辑复杂度。

使用 Token

流程:业务方在调用 API 的时候, 在 Header 里传递一个 X-Request-Id 参数(随机 id, 类似 token)

平台接收到这次请求, 判断在缓存里是否存在对应 X-Request-Id 对应的记录:如果记录存在, 表明这条消息已经被发送过, 接口返回 HTTP 412 Code

如果记录不存在, 将该记录刷到缓存里, 发送消息

Response 的 Header 也返回 X-Request-Id

缺点:流程比防重表更复杂。

幂等性优缺点

优点:实现接口的幂等性

不需要关心随机 id 的业务逻辑

缺点:增加了实现的复杂度

增加运维成本

总结

基于我们当前的业务现状,使用 X-Request-Id + 缓存来支持消息 API 的幂等操作。虽然方案依赖 Redis, 但是平台本身就有使用缓存, 运维成本这个缺点可忽略不计, 逻辑实现相对简单。 综上可以设施。

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值