敲黑板,竟然还不知道幂等是怎么回事?

新年好啊,各位朋友!今天是年后开工的第一天,不知道你们有和我一样今天敬业的在岗吗?美好的时光总是短暂的,不知不觉史上最长春节假期就这样过去了,真是心痛!

唉,多的不谈,回归今天的正题,聊聊和有关幂等方面的东西。

什么是幂等?

幂等其实是一个数学与计算机学的概念,在抽象代数中比较常见。那么在编程中,对于一个幂等操作,它主要表现为多次执行结果与单次执行结果一致,即同样的参数以及条件,无论执行多少次,最终的结果都是一致的。

当然,幂等也可以分为请求幂等和业务幂等两类:

❝

  • 请求幂等:相同参数多次请求,结果应当保持一致。
  • 业务幂等:同一个业务流程,在推进到终态之后的每次请求,响应结果都应当是一致的。在此之前,每次请求都需要执行相关的业务逻辑,直到进入终态。

❞

对于开发人员来说,保证幂等性是在日常开发过程中是必须要考虑到的。像一些转账、下单支付这类涉及金钱交易的场景,必须要保证其幂等性,否则后果是相当严重的。

如何保证幂等?

讲了上面这些,那么对于开发人员来说,在日常的开发过程中如何来保证幂等性呢?

  • 数据库唯一索引
    一般我们在进行落库新增操作时,通常会先去查这个数据记录在不在库里,不存在就落库,存在就不执行。但是对于并发较高的场景时,如果存在多个请求同时去查库,并且都没有查到记录。那么后续的话就会去执行落库新增操作,也就会产生相同的重复记录,这显然不符合我们的需求。通过使用数据库唯一索引的方式,当前一个请求插入成功后,后续请求由于索引的唯一性,再次执行就会报冲突,这也能够保证幂等性。(一定要有!)
  • 状态机
    状态机对于很多开发人员来说可能比较陌生,其作用就是为了业务状态正常的流转。例如用户下了一笔订单,此时订单状态为已下单,若成功支付,则流转至已支付待发货;若超时未支付或者手动取消,则流转至超时关闭或者已取消。每次在执行更新操作时,先拿到当前的状态进行对比,符合条件则继续更新流转。
  • 加锁(乐观锁、悲观锁或者分布式锁)
    先说悲观锁,依靠数据库层面提供的锁机制,保证操作最大程度的独占性。在整个数据处理的过程中,数据一直处于锁定状态,防止其它请求更改该数据。并且悲观锁需要在同一事务中锁住一行数据,如果事务比较长,会造成大量的请求处于等待状态,影响接口性能。再说乐观锁,其主要是通过数据版本记录来实现的,即增加版本号。每次请求之前将版本号先拿出来,后续执行更新操作时,再对该版本号进行增加。携带的版本号若与数据库中记录的版本一致,则执行更新操作,后续请求再执行的话,版本号不一致则不会再去更新数据记录。
    再来说说分布式锁,常见于使用Redis或者Zookeeper实现分布式锁,每次请求通过业务唯一ID尝试获取分布式锁,拿到锁了之后,执行后续业务逻辑。如果此次没有拿到锁,丢弃当前请求直接返回。
  • token令牌
    每次请求操作都会去生成一个唯一的token令牌,服务器端根据该令牌确保相同操作不会被执行多次,具体表现为: 1)每次请求先拿到一个token令牌,下次请求时在请求头带上这个令牌,服务端根据令牌验证判断是否能进行业务操作; 2)验证通过后,删除该令牌,下次请求再次判断token令牌。

要想解决幂等性问题,先要考虑加锁,通过对幂等号(业务唯一ID)进行加锁,之后进行幂等判断,符合条件后再执行业务更新操作。加锁的选择的话,建议选择Redis实现的分布式锁,非阻塞且高效的互斥锁,非常适合幂等控制场景。然后根据操作流水、Token令牌或者状态机判断是否符合幂等条件,最好有操作流水并且能够将幂等号作为唯一性约束。简单代码实例如下:

ini 复制代码
# 加锁
@RequestLock(keyExpression = "#request.traceId", expire = 2000)
public AjaxResult submit(RequestParams request) {
  ObjectResult objectResult = requestService.queryByParams(request);
  # 幂等判断
  if (objectResult == null) {
     # 更新
     return requestService.submit(request);
  }
  return AjaxResult.failure(0, "重复请求");
}

以上即是解决目前在日常开发过程中解决幂等问题的一种方案,大家在使用的过程中根据实际的业务需求,有问题及时发现并解决,选择合适的幂等判断条件进行方案实施,归根结底适合自己的才是最优的。

喜欢本文或者能够给你带来帮助的朋友可以一键三连,谢谢!下篇文章再会~

相关推荐
tianbin91122 分钟前
大模型训练与推理:API中转站在企业AI落地中的隐藏价值
大数据·后端·ai
打工仔折腾 AI35 分钟前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战
环境栈笔记1 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
一只小猪妖2 小时前
分布式唯一 性ID生成方法
后端
小蒜学长2 小时前
微信小程序-高校自习室管理系统(代码+数据库+LW)
java·spring boot·后端·微信小程序·自习室管理
M1A12 小时前
告别代码风格之争:在 VS Code 中用 Black 一键格式化 Python
后端
IT_陈寒2 小时前
Python多进程共享变量这个坑,差点让我加班到凌晨
前端·人工智能·后端
诸神缄默不语3 小时前
Zotero安装和简单使用教程
程序员
撸串-研究生3 小时前
springboot福利院管理系统73979
java·spring boot·后端·福利院管理系统