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

 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做到了分布式锁,只有这笔订单支付请求完成,下次请求才能进来。

在 Redis 中,使用 SETNXSET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果

<?php

$ok = $redis->setNX($key, $value);

if ($ok) {
    $cache->update();
    $redis->del($key);
}

?>

 

233

参考文档


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

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

https://blog.huoding.com/2015/09/14/463

 

转载于:https://www.cnblogs.com/lemos/p/11080157.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值