解决方案:如何防止数据重复插入?

  • 时间:
  • 浏览:1
  • 来源:极速快3_快3IOS下载_极速快3IOS下载

摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢!

目录

  1. 怎么么要防止数据重复插入?
  2. 防止方案实战
  3. 可落地小总结

疑问起源,微信小线程抽风 wx.request() 重复请求服务器提交数据。后端服务也很简单,伪代码如下:

class SignLogService {
    public void saveSignLog(SignLogDO log) {
        

发现数据库会存在重复数据行,提交时间一模一样。但业务需求是能要能 有多余的 log 老出,这明显是个疑问。

疑问是,重复请求导致 的数据重复插入。这疑问造成的后果很明显:

  • 数据冗余,可能不单单多二根绳子
  • 或者 业务需求能要能 有多余数据,造成服务疑问

疑问如图所示:

防止依据:怎么将 同请求 A,不执行插入,本来读取前另一有一一5个 请求插入的数据并返回。防止后流程应该如下:

1.单库单表防止方案

  • 唯一索引 + 唯一字段
  • 幂等

后面 说的那种业务场景:sign_log 表会有 user_id、sign_id、sign_time 等。没办法 每次签到,每我人及所有所有每天要能要能 二根绳子 签到记录。

数据库层采取唯一索引的形式,保证数据记录唯一性。即 UNIQUE 约束,UNIQUE 约束唯一标识数据库表中的每条记录。另外,user_id,sign_id,sign_time 另一有一一5个 组大概唯一字段。创表的伪代码如下:

CREATE TABLE sign_log
(
id int NOT NULL,
user_id int NOT NULL,
sign_id int,
sign_time int,
CONSTRAINT unique_sign_log UNIQUE (user_id,sign_id,sign_time)
)

重点是 CONSTRAINT unique_sign_log UNIQUE (user_id,sign_id,sign_time)。有个小疑问,数据量大的事先,每条记录时会有对应的唯一索引,比较耗资源。没办法 另另一有一一5个就行几时?

答案是不行,服务过高 健壮。第另一有一一5个 请求插入成功,第5个请求直接报错,Java 服务会抛出 DuplicateKeyException 。

简单的幂等写法操作即可,伪代码如下:

class SignLogService {
    public SingLogDO saveSignLog(SignLogDO log) {
        

的确,流量时会很大,本来算很高并发。重复写疑问,另另一有一一5个防止即可。那大流量、高并发场景咋搞

2.分库分表防止方案

流量大了后,单库单表会演变成分库分表。没办法 基于单表的唯一索引形式,在碰到分表就无法保证呢,插入的地方可能是另一有一一5个 分表 A1 和 A2。

防止思路:将数据的唯一性条件倒入或者 存储,并进行锁控制

还是后面 的例子,每天,每次签到,每我人及所有所有要能要能 二根绳子 签到记录。没办法 使用分布式锁 Redis 的防止方案。大致伪代码如下:

a.加锁

  • lockKey 最简单的是 user_id + sign_id + sign_time
  • expireTime 设置为一天

b.解锁

c.幂等代码加强

class SignLogService {
    public SingLogDO saveSignLog(SignLogDO log) {

        

你这俩方案还是时会很成熟图片 期期 图片 期,朋友参考下即可。

防止方案实战中,了解具体术。归纳如下:

  • 幂等:保证多次同意请求后结果一致
  • 并发控制:单表唯一索引、分布式多表分布式锁
  • 降级兜底方案:分布式锁锁失效 – 考虑乐观锁兜底

参考资料

  • 重复插入方案: http://www.bysocket.com/archives/2266
  • 《阿里巴巴 Java 开发手册》

以下专题教程你爱不爱我您会有兴趣

  • 《Spring Boot 2.x 系列教程》
  • 《Java 核心系列教程》

(关注微信公众号,领取 Java 精选干货学习资料)