1,什么是幂等性
即相同的多次请求,只执行一次。
2,简述怎么保证幂等性?
单机部署的场景
使用唯一标识符:
在客户端发起请求时,附加一个唯一的请求标识符(如 UUID)。服务端接收到请求后,检查这个标识符是否已经处理过。如果已处理过,直接返回之前的结果;否则,处理请求并记录标识符。
分布式部署场景
借用脱离服务自身存储外的第三方工具,如:redis缓存,mysql中的唯一约束,s3存储等都可以
3,举个栗子
以数据库为例
首先简单创建一张表
CREATE TABLE `roejrtest`.`uq` (`id` int NOT NULL AUTO_INCREMENT,`key` varchar(255) NULL,`value` varchar(255) NULL,`uuid` varchar(200) NOT NULL,PRIMARY KEY (`id`),UNIQUE INDEX `index_uq_uuid`(`uuid`)
);
创建接口进行测试(基础的就不全部展示了),有需要请查看https://blog.csdn.net/weixin_54925172/article/details/139564046?spm=1001.2014.3001.5501
controller类
package com.luojie.controller;import com.luojie.controImpl.IdempotenceTestImpl;
import com.luojie.moudle.IdempotenceTestModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;@RestController
public class IdempotenceTestController {@Autowiredprivate IdempotenceTestImpl idempotenceTest;@PostMapping("/idempotence/test")public void idempotenceTest(@RequestHeader("x-uuid") String uuid, @RequestBody IdempotenceTestModule module) {idempotenceTest.setup(uuid, module);}
}
实现类
package com.luojie.controImpl;import com.luojie.dao.mapper2.Mapper2;
import com.luojie.moudle.IdempotenceTestModule;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class IdempotenceTestImpl {@Autowiredprivate Mapper2 mapper2;public void setup(String uuid, IdempotenceTestModule module) {// 检查是否已经存在String getuuid = mapper2.getuuid(uuid);if (StringUtils.isNotBlank(getuuid)) {throw new IllegalArgumentException("已经处理过了");}// 不存在则继续module.setUuid(uuid);mapper2.insertUq(module);}}
测试,第一次请求时,检查未被拦截
后续请求时,被拦截