幂等源于数学,表达的是N次变换与1次变换的结果相同。如果一个方法调用一次和调用多次产生的效果是相同的。幂等函数或者幂等方法,是指可以使用相同参数执行,并能获得相同结果的函数,这些函数不会影响系统的状态,也不用担心重复执行会对系统造成改变。
HTTP GET 方法用于获取资源,不应有副作用,所以是幂等的。Select可以说是天生的幂等。
这里指的是N次和1次具有相同的副作用,而不是返回相同的数据。
HTTP DELETE 方法用于删除资源,有副作用,但是它应该满足幂等性,调用一次和调用N次的副作用是相同的,删除一个文章不会造成其他数据的误删。
HTTP POST 所对应的URI尾资源的接收者。发表一篇文章,两次相同的POST请求会在服务器端创建两份资源,所以POST方法不具备幂等性。
HTTP PUT 所对应的URI是创建或者更新资源。创建或者更新一个ID唯一的文章,对同一个URI进行多次PUT和一次PUT是相同的,因此PUT方法具有幂等性。
幂等性讨论:
第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用,这里的副作用指不会对结果产生破坏或者产生不可预料的结果。
分布式微服务在哪一层解决幂等性问题?
写请求、读请求?
读请求不会产生副作用。不改变数据的操作不需要做幂等。
写请求因为修改数据,需要做幂等。
对于Insert操作,分为两种情况:
自增主键
多次Insert后会产生数据相同,但是主键不相同的数据。
业务主键
第二次Insert时,会因为主键冲突而报错。
对于Delete操作,分为两种情况:
相对值删除
比如删除 top 数据,多次操作会导致幂等问题。
绝对值删除
通过Id删除,只会删除一个数据。
相对值更新
update product_info set prince = price + 99 where id = 1234 ;
无法保证幂等性
绝对值更新
update product_info set prince = 99 where id = 1234 ;
可以保证幂等性
所以对数据写的时候考虑幂等性。幂等性还分为广义的幂等性和狭义的幂等性,单库属于狭义的幂等性,而如今分布式系统中,需要分布式事务保证广义的幂等性。
按钮只可操作一次,一般是提交完成后按钮置灰或者loading状态,这里使用一些js组件实现,消除用户因为重复点击而产生的副作用,比如添加操作,由于点击两次而产生的两条记录。
缺点:用户可能会绕过js验证,所以前端实现的幂等性只能防止小白。
产品上允许重复提交,但要保证重复提交不产生副作用,进入页面时申请一个Token,后面的所有请求都带上这个Token,根据Token来避免重复请求。
在提交后执行页面重定向,就是所谓的Post-Redirect-Get模式。当用户提交表单时,重定向到一个成功界面,防止用户刷新导致的重定向提交,同时也不会出现浏览器表单重复提交的警告,也能消除浏览器前进和后退导致的同样出伏提交问题。
在服务器端,生成一个唯一标识符,存入Session,同时将它写入表单的隐藏中,然后提交表单,服务端会判断session中的标识符和表单中的标识符是否一致,如果一致,则表示首次提交,并将标识符移除,否则是重复提交。
像上文中说过的insert业务主键,可以有效的保证幂等性。
申请Token+业务操作两个阶段,整个流程如下图所示,但是业务操作需要加分布式锁来处理。
对于更新操作,设定更新状态操作,结合CAS思想,假设订单状态有待支付、支付中、支付成功、支付失败、订单超时等,在SQL语句where中加上status = 期望的值
然后进行修改,这样也只会修改一次。
更新已有数据,进行加锁更新,设计表结构时使用乐观锁,通过version来做乐观锁,即可保证效率,又能保证幂等性。乐观锁的version版本在更新业务时是递增的。
防重表类似于锁的机制,保证当前处理订单只有一个线程。但是对于处理完成后,此订单的第二次操作同样会带来副作用,这里就需要配合其他机制来保证了,比如状态机。
此方案是解决单机的幂等性问题的,先查询在判断是否插入,但是并发的时候需要加锁处理。
进入方法时,先去获取锁,如果获取锁了,进行业务操作,如果没获取,等待锁的释放。同时分布式锁还有很多的细节,这里先不说了。
常用解决分布式锁的工具有Redis、zookeeper。思路类似于防重表。
按照消息的顺序来保证幂等性,同步改为异步,高吞吐量,但是不能同步返回结果。
本文发布于:2024-01-28 01:09:19,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063753653749.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |