什么是幂等性?
是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。(但是有些场景是不需要保证幂等性的)
1.悲观锁
只针对 innodb 的 mysql
sql行级锁 select * from table_name where id ="" for update;
如果事务耗时比较长,会造成大量的请求等待,影响接口性能。
2.乐观锁
在表中增加一个timestamp
或者version
字段,这里以version
字段为例。
update table set a=a+1,version=version+1 where id ="" and version =1;
由于第一次请求version
等于1
是可以成功的,操作成功后version
变成2
了。这时如果并发的请求过来,再执行相同的sql: 查询条件 version =1 查不到条件数据
具体步骤:
- 先根据id查询 table,包含version字段
- 根据id和version字段值作为where条件的参数,更新表,同时version+1
- 判断操作影响行数,如果影响1行,则说明是一次请求,可以做其他数据操作。
- 如果影响0行,说明是重复请求,则直接返回成功.
3.唯一索引
alter table `` add UNIQUE KEY `` (``);
代码中java
程序需要捕获:DuplicateKeyException
异常,如果使用了spring
框架还需要捕获:MySQLIntegrityConstraintViolationException
异常
在异常中可以根据实际业务需要告警还是打印日志
4.状态机
比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态。如果这些状态的值是有规律的,按照业务节点正好是从小到大,我们就能通过它来保证接口的幂等性。
5.加分布式锁
根据业务场景去定义分布式锁的颗粒度,加锁中处理业务逻辑,锁未释放,下一次请求不会被执行
6.token校验
具体步骤:
- 用户访问页面时,浏览器自动发起获取token请求。
- 服务端生成token,保存到redis中,然后返回给浏览器。
- 用户通过浏览器发起请求时,携带该token。
- 在redis中查询该token是否存在,如果不存在,说明是第一次请求,做则后续的数据操作。
- 如果存在,说明是重复请求,则直接返回成功。
- 在redis中token会在过期时间之后,被自动删除。