Q1: 什么是幂等性?
A: 在数学中表示某一元运算为幂等时,其作用在任一元素两次后会和其作用一次的结果相同。
在计算机中编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。
Q2: 什么是接口幂等性?
A: 在HTTP/1.1中,对幂等性进行了定义。它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。
Q3: 为什么需要实现幂等性?
A: 会出现如下问题:
- 前端重复提交表单: 在填写一些表格时候,用户填写完成提交,很多时候会因网络波动没有及时对用户做出提交成功响应,致使用户认为没有成功提交,然后一直点提交按钮,这时就会发生重复提交表单请求。
- 用户恶意进行刷单: 例如在实现用户投票这种功能时,如果用户针对一个用户进行重复提交投票,这样会导致接口接收到用户重复提交的投票信息,这样会使投票结果与事实严重不符。
- 接口超时重复提交: 很多时候 HTTP 客户端工具都默认开启超时重试的机制,尤其是第三方调用接口时候,为了防止网络波动超时等造成的请求失败,都会添加重试机制,导致一个请求提交多次。
- 消息进行重复消费: 当使用 MQ 消息中间件时候,如果发生消息中间件出现错误未及时提交消费信息,导致发生重复消费。
Q4: Restful API 接口的幂等性?
A:参考下图:
Q5: 实现幂等性?
1. 数据库唯一主键控制:
一般来说唯一主键比较适用于“插入”时的幂等性,其能保证一张表中只能存在一条带该唯一主键的记录。
要求:唯一主键,需要使用分布式主键策略,不要使用数据库自增主键
策略选择:snowflake算法 + 时钟同步 + UUID备选方式,或采用 redis自增方式 均可。
主要流程:
- ① 客户端执行创建请求,调用服务端接口。
- ② 服务端执行业务逻辑,生成一个分布式 ID,将该 ID 充当待插入数据的主键,然后执数据插入操作,运行对应的 SQL 语句。
- ③ 服务端将该条数据插入数据库中,如果插入成功则表示没有重复调用接口。如果抛出主键重复异常,则表示数据库中已经存在该条记录,返回错误信息到客户端。
2. 数据库乐观锁:
- 数据库乐观锁方案一般只能适用于执行“更新操作”的过程,
- 在对应的数据表中多添加一个字段,充当当前数据的版本标识。
- 这样每次对该表的这条数据更新时,都会将该版本标识作为一个条件,值为上次待更新数据中的版本标识的值。
这样每次执行更新时候,都要指定要更新的版本号,如下操作就能准确更新 version=5 的信息:
UPDATE my_table SET price=price+50,version=version+1 WHERE id=1 AND version=5
上面 WHERE 后面跟着条件 id=1 AND version=5 被执行后,id=1 的 version 被更新为 6,所以如果重复执行该条 SQL 语句将不生效,因为 id=1 AND version=5 的数据已经不存在,这样就能保住更新的幂等,多次更新对结果不会产生影响。
其他方法还有: 防重 Token 令牌、传递唯一序列号、根据业务信息生成一致性hash的redis key值等方法,这里就不展开介绍了,本质都是一样的,
最后. 实现幂等性需要先理解自身业务需求,根据业务逻辑来,
选择一个自己熟悉的路线来实现,这样才最合理的.
本文到此为止,谢谢阅读。