由表单重复提交引发的幂等性思考

Posted lemos

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由表单重复提交引发的幂等性思考相关的知识,希望对你有一定的参考价值。

 1. 什么时候需要实现幂等性接口?

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。既然是这样我们的查询和删除不就是多次执行的结果和一次执行的相同吗。是的,查询和删除拥有天然的幂等性,当然删除这个第一次执行和后面执行的返回值可能会有所不同,但是最终的效果是一致的。所以需要我们额外实现的幂等性接口主要是新增和更新操作。

 

2.实现幂等的解决方案

①  token 机制防止表单重复提交

 redis 预存一个 token 并分发到客户端。当客户端提交请求时,携带这个 token,服务端操作 redis 删除这个 token,如果操作成功则请求放行,否则为重复请求或非法请求。

 

② 唯一索引,防止新增脏数据

设置关系性数据库唯一键约束(一致性保证)。

 

③悲观锁与乐观锁

悲观锁,就是悲观的认为数据会被改变,在数据修改的过程中始终是加锁的。其他线程无论是读还是写都无法拿到数据。因为默数据倾向会变,并发写较高时,不用每次都要判断。

select * from t_goods where id=1 for update;

乐观锁,只会在update的一瞬间加锁,其余处理过程中并不加锁。乐观锁每次只会有一个线程执行成功,其他线程因为条件发生了改变,而执行失败,这样就避免了数据覆盖的可能性。因为数据倾向不变,并发写较低,但是并发读较高,不因表锁/行锁而浪费等待时间。(条件字段一最好是主键或者唯一索引,防止锁表或者锁无限)

UPDATE t_goods
SET STATUS = #status,name=#name,version=version+1 
WHERE
    id = #id and version=#version 

 

④分布式锁

以电商支付为案例,订单发起支付请求,支付系统首先查询订单是否已经支付,如果已经支付,直接返回已支付。如果未支付去Redis缓存中查询是否存在该订单号的Key,如果不存在,则向Redis增加Key为订单号,已存在返回重复操作。再次查询是否完成支付,如果没有则进行支付,支付完成后删除该订单号的Key。通过Redis做到了分布式锁,只有这笔订单支付请求完成,下次请求才能进来。相比唯一索引,将并发放到了缓存中,较为高效。思路相同,同一时间只能完成一次支付请求。

 

233

参考文档


https://juejin.im/post/5b4977ae5188251b146b2fc8

https://www.cnblogs.com/laoyeye/p/9557269.html

以上是关于由表单重复提交引发的幂等性思考的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 的幂等性 分析 POST 表单重复提交

如何避免重复提交?分布式服务的幂等性设计!

幂等性

阿里面试官:接口的幂等性怎么设计?

Filter+Redis解决项目之间调用的幂等性

京东面试官:接口的幂等性怎么设计?