0%

幂等性

一、幂等的数学概念

  • 一元计算中,x为某集合的任意数,如果满足f(x)=f(f(x)),则称f运算具有幂等性。
    比如绝对值abs(a)=abs(abs(a))为幂等函数
  • 二元运算,x为集合任意数,如果f(x,x)=x,则称f运算也有幂等性。
    比如max(x,x)=x也幂等函数

二、幂等在开发中的概念

  • 同一个系统,在同样条件下,一次请求和重复多次请求对资源的影响是一致的,则称此操作是幂等的。
  • 要求幂等例子:微信支付,一笔订单应当只扣一次钱,那么无论网络等原因导致重新付款,都只能扣一次

三、HTTP协议与幂等性

-查询操作(GET):幂等。GET用于获取资源,不对资源进行改变。注意幂等体现在对系统资源的改变,而不是返回数据的结果。

  • 删除操作(DELETE):幂等。虽然改变了资源,但第一次和第N次删除操作对系统的作用是相同的。(虽然第一次返回200,N-1次返回404)
  • 修改操作(PUT):幂等。PUT协议只能做固定的操作,比如修改账号金额为1000元,而不是账户中减少50.只是在第一次改了,N-1次都是重复操作,资源不会再变
  • 新增操作(POST):非幂等。POST用请求实体来创建新的资源。幂等需要业务中实现。

参考:https://restfulapi.net/idempotent-rest-apis/

四、实现幂等性的方案

  • 去重表:利用数据库的特性来实现幂等。通常是在表上构建一个唯一索引,那么只要某一个数据构建完毕,后面再次操作也无法成功写入。
    适用于在业务中有唯一标识的插入场景。比如订单支付中,订单ID可以作为唯一标识作为唯一索引,将支付数据写入去重表中。从而导致第二次以后无法插入表单。
  • 乐观锁(版本控制):只是更新为固定值,没必要加锁。加锁是在资源不固定,例如账户金额减少50元这种情况。
    UPDATE tab1 SET col1=col-1,version=version+1 WHERE id=#id# and version=#version#
    1581757597(1)
    乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,
  • token:后端生成token给前端,前端提交把token给后端进行一致性校验;若一致,则删除token;若前端再提交,后端token已删除,则不一致,避免了重复提交。
    此时token何时生成就成为关键:在用户提交时生成,则每次都是新token,不是幂等问题。在博客中,用户进入编辑页面,则要生成token。 Token 生成的时机必须保证能够使该操作具多次执行都是相同的效果才行。
    Session原理中有涉及
  • 状态标识:一般用于业务流程较长,修改数据较多场景中。比如“创建订单 -> 订单支付\取消 -> 账户计算 -> 通知商户“”,当做完一个步骤就修改对应的状态标识。
  • 支付缓冲区:把订单的支付请求都快速地接下来,一个快速接单的缓冲管道。后续使用异步任务处理管道中的数据,过滤掉重复的待支付订单。优点是同步转异步,高吞吐量。缺点是不能及时地返回支付结果,需要后续监听支付结果的异步返回