幂等性——幂等设计

幂等设计

幂等性:不管是执行一次还是多次,产生的结果和影响都是相同的

​ 如:保证相同的ID组合只会插入一条数据到DB里面,如果一个请求是save,后续的都应该update这条数据

属于具有幂等性的SQL:

//指定查询
select  opcd from info_oper where opid='000000'

//指定更新
if exists(select 1 from info_oper where opid='000000')   
begin
	update  info_oper set  opcd='9999' where opid='000000'
end

//指定删除
if exists(select 1 from info_oper where opid='000000')   
begin
	delete  from info_oper where opid='000000'
end

幂等的缺点:——因此,除了业务上的特殊要求外,尽量不提供幂等的接口

  1. 使客户端逻辑处理变得简单,但服务逻辑却变得复杂

  2. 把并行执行的功能改为串行执行,降低了执行效率

满足幂等服务的需要在逻辑中至少包含两点:

  1. 先查上一次的执行状态,如果没有则认为是第一次请求
  2. 在服务改变状态的业务逻辑前,保证防重复提交的逻辑

遇到的具体业务实例:上线sql、hangfire定时删除数据

需要使用幂等的情况:业务开发中,经常会遇到重复提交的情况,无论是由于网络问题无法收到请求结果而重新发起请求,或是前端的操作抖动而造成重复提交情况。具体如:用户在APP上连续点击了多次提交订单,后台应该只产生一个订单;支付宝发起支付请求,由于网络问题或系统BUG重发,支付宝应该只扣一次钱等

分布式系统中一定要考虑幂等的设计,因为相较于进行分布式事务设计,幂等设计轻量级的多。

  1. 如果接入的是服务端,可以由服务端确保生成唯一的标识符
  2. 如果是接入最终用户的浏览器,则可以由自己的服务器先生成一个标识符发送给浏览器,当用户提交表单的时候,以此来认证是否为二次提交。
  3. 如果确认为二次提交,则把第一次的处理结果再次返给请求端

常用的保证幂等的手段:

  1. MVCC方案

    多版本并发控制,该策略主要使用update with condition(更新带条件来防止)来保证多次外部请求调用对系统的影响是一致的。在系统设计的过程中,合理的使用乐观锁,通过version或者updateTime(timestamp)等其他条件,来做乐观锁的判断条件,这样保证更新操作即使在并发的情况下,也不会有太大的问题。

  2. 去重表——利用唯一索引

    在插入数据的时候,插入去重表,利用数据库的唯一索引特性,保证唯一的逻辑

  3. 悲观锁

    select for update,整个执行过程中锁定该订单对应的记录。但值得注意的是:在数据库读大于写的情况下尽量少用

  4. select+insert

    并发不高的后台系统,或者一些任务JOB,为了支持幂等,支持重复执行,简单的处理方法是,先查询下一些关键数据,判断是否已经执行过,在进行业务处理,就可以了。注意:核心高并发流程不要用这种方法。

  5. 状态机幂等

    在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机,就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。

  6. Token(令牌)机制 – (ToKen:令牌(临时),一般作为邀请、登录系统使用)

    业务要求:页面的数据只能被点击提交一次

    发生原因:由于重复点击或者网络重发,或者nginx重发(HTTP和反向代理服务器,支持容错和负载均衡)等情况会导致数据被重复提交

    解决办法:

    • 集群环境:采用token加redis(redis单线程的,处理需要排队)
    • 单JVM环境:采用token加redis或token加jvm内存

    处理流程:

    • 数据提交前要向服务的申请token,token放到redis或jvm内存,token有效时间
    • 提交后后台校验token,同时删除token,生成新的token返回

    token特点:要申请,一次有效性,可以限流

提交订单时保证幂等的方法:

使用去重表的方法:
1.后端创建一个流水表用来暂存用户下单请求信息(主键是有前端发送创建订单请求时发送给后端的流水ID)
2.在用户从前端确认下单的时候生成一个唯一流水ID,连同订单信息一起请求发送给后端,在用户未收到后端的反馈信息之前前端界面应该处于等待状态(这时候流水ID不变),当收订单生成成功的反馈信息后,清空流水ID;当出现网络异常,订单生成失败的时候,应给出生成订单失败的提示,这时若用户停留在当前界面重新提交订单,流水ID不变,直至用户放弃提交订单,返回或跳转至其他界面,清空或者更新流水ID

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值