一、摘要
对于投入运营的软件系统,最近小编在巡检项目数据库的时候,发现某些表存在不少的重复数据,对于这样的脏数据,初步分析大致的来源有以下可能:
- 1.由于用户误操作,多次点击表单提交按钮
- 2.由于网速等原因造成页面卡顿,用户重复刷新提交页面
- 3.黑客或恶意用户使用 postman 等网络工具,重复恶意提交表单
这些情况都可能会导致表单重复提交,造成数据重复,比如订单表,重复提交订单数据所造成的问题,可能不仅仅是数据上的混乱,也会造成业务混乱。
那么问题来了,我们该如何防止用户重复提交数据呢?
方案实践如下!
二、方案实践
下面我们以防止重复提交订单为例,向大家介绍最简单的、成本最低的解决办法。
我们先来看一张图,这张图就是本次方案的核心流程图。
实现的逻辑,流程如下:
- 1.当用户进入订单提交界面的时候,调用后端获取请求唯一ID,并将唯一ID值埋点在页面里面
- 2.当用户点击提交按钮时,后端检查这个唯一ID是否用过,如果没有用过,继续后续逻辑;如果用过,就提示重复提交
- 3.最关键的一步操作,就是把这个唯一ID 存入业务表中,同时设置这个字段为唯一索引类型,从数据库层面做防止重复提交
防止重复提交的大体思路如上,实践代码如下!
2.1、给数据库表增加唯一键约束
以订单表为例,新增一个request_id
字段,并设置为唯一约束,结构如下:
CREATE TABLE tb_order (
id bigint(20) unsigned NOT NULL,
order_no varchar(100) NOT NULL,
....
request_id varchar(36) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY uniq_request_id (request_id) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2、编写获取请求唯一ID的接口
@RestController
@RequestMapping("api")
public class CommonController {
/**
* 获取getRequestId
* @return
*/
@RequestMapping("getRequestId")
public ResResult getRequestId(){
String uuid = UUID.randomUUID().toString();
return ResResult.getSuccess(uuid);
}
}
2.3、业务提交的时候,检查唯一ID
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 下单
* @param request
* @return
*/
@PostMapping(value = "order/confirm")
public ResResult confirm(@RequestBody OrderConfirmRequest request){
//调用订单下单相关逻辑
if(StringUtils.isEmpty(request.getRequestId())){
return ResResult.getSysError("请求ID不能为空!");
}
if(request.getRequestId().length() != 36){
return ResResult.getSysError("请求ID格式错误!");
}
//检查当前请求唯一ID,是否已经存在,如果存在,再提交就是重复下单
Order source = orderService.queryByRequestId(request.getRequestId());
if(Objects.nonNull(source)){
return ResResult.getSysError("当前订单已经提交成功,请勿重复提交");
}
orderService.confirm(request);
return ResResult.getSuccess();
}
}
如果是并发请求也不用担心,因为数据库表已经设置了唯一索引,尤其只有一条有效数据会插入成功,可以防止重复的数据产生。
三、小结
对于下单流量不算高的系统,可以采用这种请求唯一ID
+数据表增加唯一索引约束
的方式,来防止接口重复提交!
虽然简单粗暴,但是十分有效!
可能有的人会问,看上面的代码生成请求唯一 ID 很简单,为啥不直接前端生成一个请求唯一ID
,然后提交呢?
之所以把获取请求唯一ID
的生成规则放在后端,好处就是生成规则可以自己定义,也并不一定要用uuid
来生成,也可以用雪花算法,或者自己设计一套计算规则,保证当前业务提交时请求ID是唯一的,比如事先生成唯一的订单号,作为请求唯一ID,然后再提交,规则放在后端来生成,会更加灵活!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
版权声明:
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com