业务应用系统的幂等性控制

一 、天然幂等

1、查询

查询一次和查询多次一样的。

2、删除数据

删除数据,仅仅第一次删除是真正的操作数据,之后删除直接返回成功,这样保证了幂等。

二、锁

1、MVCC方案(乐观锁)

多版本并发控制,update with condition,更新带条件,这也是在系统设计的时候,合理的选择乐观锁,通过version或者其他条件,来做乐观锁,这
update tablexxx set name=#name#,version=version+1 where version=#version#
update table
xxx set quality=quality-#subQuality# where quality-#subQuality# >= 0 。

2、悲观锁

select * from table where id = ‘xxx’ for update;
要注意的是,id字段一定要是主键或者唯一索引,否则会导致锁表。
悲观锁的使用一般伴随事务一起使用,数据锁定事件可能会很长,要根据实际情况慎用

3、分布式锁

三、唯一索引

1、 单独的去重表

如果涉及到的去重的地方特别多,例如ERP系统中有各种各样的业务单据,每一种业务单据都需要去重,这时候,可以单独搞一张去重表,在插入数据的时候,插入去重表,利用数据库的唯一索引特性,保证唯一的逻辑。

2、 插入数据的唯一索引

插入数据的唯一性,可以通过业务主键来进行约束,例如一个特定的业务场景,三个字段肯定确定唯一性,那么,可以在数据库表添加唯一索引来进行标示。

保证幂等性

其实保证幂等性主要是三点:

  • 对于每个请求必须有一个唯一的标识,举个例子:订单支付请求,肯定得包含订单id,一个订单id最多支付一次,对吧
  • 每次处理完请求之后,必须有一个记录标识这个请求处理过了,比如说常见的方案是在mysql中记录个状态啥的,比如支付之前记录一条这个订单的支付流水,而且支付流水采
  • 每次接收请求需要进行判断之前是否处理过的逻辑处理,比如说,如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,orderId已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。
  • 这里只是一种思想,也可以用redis用orderId作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。

四、API层面的幂等

1、select+insert

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

2、token+redis

在数据提交前要向服务器申请带有有效时间的Token,然后Token放到Redis或JVM内存中,
当数据正式提交到后台要校验Token并删除Token。

五、状态机幂等

业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,
这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,
理论上是不能够变更的。

你可能感兴趣的:(工作,数据库,java)