**
一、什么是分布式的幂等性
**
1.定义:用户对于同一操作发起的一次请求或者多次请求的结果是一致的
2.示例:
以SQL为例,有下面三种场景,只有第三种场景需要开发人员使用其他策略保证幂等性:
SELECT col1 FROM tab1 WHER col2=2,无论执行多少次都不会改变状态,是天然的幂等。
UPDATE tab1 SET col1=1 WHERE col2=2,无论执行成功多少次状态都是一致的,因此也是幂等操作。
UPDATE tab1 SET col1=col1+1 WHERE col2=2,每次执行的结果都会发生变化,这种不是幂等的。
INSERT INTO table_name VALUES (value1,value2,value3,…); 如果insert操作中存在唯一键约束,幂等操作;如果不存在,不是幂等操作
DELETE FROM tab1 WHERE ID=2 幂等操作
除此之外,还有很多的幂等与非幂等操作,比如MQ消息重复消费,接口重复调用等,具体情况具体分析
二、什么样的情况会产生幂等性问题
1.表单重复提交||接口重复调用
2.消息队列消息处理之后回调之前,MQ挂掉,消息重复消费
3.网络问题导致的多次服务调用
……
等等。
综合上述不难发现都是多次调用接口,导致可能产生幂等性问题。
三、如何保证接口的幂等性
1.业务
(1)新增:业务表添加约束条件 如果你的数据库将来都不会分库分表,那么可以在业务表字段加上唯一约束条件(UNIQUE),这样相同的数据就不会保存为多份。
更新:
(2)更新:更新已有的数据,没有必要对业务进行加锁,设计表结构时使用乐观锁,一般通过version来做乐观锁,这样既能保证执行效率,又能保证幂等。例如:
UPDATE tab1 SET col1=1,version=version+1 WHERE version=#version#
不过,乐观锁存在失效的情况,就是常说的ABA问题,不过如果version版本一直是自增的就不会出现ABA的情况
2.全局唯一ID: 比如每次请求携带一个全局唯一的流水号,操作之前,先去redis或者数据库(看各系统具体情况)查这个流水号是否已存在,已存在不操作。不存在,继续业务逻辑
3.使用 redis: 如果你的系统是分布式的,又做了分库分表,那么可以使用 redis 来做记录,把消息 id 存在 redis 里,下次再有重复消息 id 在消费的时候,如果发现 redis 里面有了就不能进行消费
4.维护一张消息表: 维护一张消息表,每次操作前查询消息是否在消息表已存在,已存在不操作,不存在,继续业务操作
方法很多,具体情况,具体分析,没有最好的,只有最合适的。
-------与君共勉!