关于幂等那些事

144 阅读3分钟

何为幂等

"在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同" ————百度百科 我们从百度百科的定义来看幂等,应用到互联网最常见的rpc与消息交互场景,简单来说,rpc接口消息的幂等性即: 1.对于rpc的调用方来说,同样的请求调用多次时,与一次请求的结果一致,不会产生额外非预期的影响。 2.对于消息的消费方来说时,消息重复时,重复消费与消费一次的结果一致不会产生额外的影响。

工作中遇到的那些幂等方式

下面介绍下作者在工作中实际使用过的幂等方式,可能不是很全面,欢迎补充,互相交流学习。

乐观锁

乐观锁的方式常常用于状态的更新,比如用户选购商品后,会生成订单【待支付】,用户进行支付后,订单由【待支付】状态修改为【已支付】状态.

update order_table set order_status = '已支付' where order_sn = 'xxx' and order_status = '待支付'

乐观锁的实现方式如上,在实际进行变更操作时会先判断订单状态是否是预期状态,符合预期状态,才会进行更新,否则不会进行更新,可以想到,在不考虑其他场景会修改当前订单的状态时,乐观锁天然支持幂等。

正如乐观锁的思想:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。 因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作

而当订单状态存在其他数据修改操作来源时,乐观锁由于未对资源进行加锁,多方皆可进行修改互相影响,这样导致状态管理混乱容易出错,这是业务无法接受的。

幂等表

幂等表应该是我工作中使用最多的幂等方式了,简单来说其要求每次请求时携带一个标识请求唯一的业务编号, 而时间处理业务请求时,会先查询幂等表中是否存在该业务编号,若存在,则说明请求已经处理过了,不再进行处理,则将业务请求存储为待处理状态,并在处理成功后将状态更新为处理成功,若处理失败,此时可根据业务特性选择重试或回滚等。

下面以一段使用幂等表处理消息幂等实现代码来说明: void handle(Message msg) { // 获取消息唯一id String msgUniqueId = msg.getUniqueId(); // 获取分布式锁(分布式锁也可以用幂等表构建唯一索引来实现) redis.getLock(); // 判断幂等表中是否存在该消息请求id if (existMsgId(msgUniqueId)) { // 消息幂等 return; } // 保存消息请求id到幂等表 saveMsgId(msUniqueId);

// 业务逻辑处理
....
// 释放分布式锁
redis.releaseLock()

}

终态幂等

幂等表可以解决大多数问题,但有时候我们可能并不需要额外存储便能解决幂等,而是通过终态来解决幂等,这里主要解决业务操作的目标是到达终态,终态不会变更,因此请求处理时,提前判断业务是否到达终态,若是则幂等无需处理,狗则将业务更新为终态。

总结

本文介绍了个人在工作中常常遇到的幂等问题的处理方式,而实际业务往往更加复杂,但万变不离其宗,只要我们掌握幂等的核心思想,抓住主线,便可轻松解决问题。