解决高并发环境下数据插入重复问题

背景描述

应用框架:Spring Boot + mybatis
数据库:Sqlserver
系统一个业务号只允许存在一笔正在处理的预约订单,当多个用户同时发送多笔业务号相同的预约订单,我们发现数据库中也会存在多笔业务号相同的预约订单。而且业务号在表中还不能是主键。


1.原因分析

由于短时间内客户可能连续推送了两条重复的数据,两条数据时间间隔非常小,因此导致了我们的

if(业务号存在){
   // ...
}

否则订单入库

if 里面操作还没有执行完毕,第二条拥有相同数据的线程已经进入并通过了if的检验,导致数据库存储了两条相同的数据。


2.解决方法

(1)使用synchronized同步代码块即加同步锁
synchronized(this){
   //...
}

这样会导致其他正常数据的推送线程也被阻塞,影响效率。因此不采用。我们考虑只对重复数据加锁。

String lonNbr=... ;
synchronized(lonNbr.intern()) {
    //...
}   

使用String作为同步锁必须注意产生不同对象的问题,必须保证线程拿到的是同一个String对象,但这个有时很难保证。这个时候就得使用intern()方法,这样就是直接获取的是字符串的值本身,而不是取的String的对象。
Java中String做为synchronized同步锁使用详解

这种加同步锁的方法在负载均衡下的多台应用服务器会失效!

(2)分布式锁

基于缓存(Redis等)实现分布式锁;
基于Zookeeper实现分布式锁;

分布式锁简单入门以及三种实现方式介绍

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行;当...
    AI乔治阅读 550评论 0 12
  • 1.解决信号量丢失和假唤醒 public class MyWaitNotify3{ MonitorObject m...
    Q罗阅读 912评论 0 1
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,503评论 1 15
  • 前言 个人认为,学习,内容越多、越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的。这篇文章主要...
    尧淳阅读 684评论 0 17
  • 今天阅读卡耐基传第16章——第21章,这几章讲述卡耐基把演讲的兴趣变成了工作。 1.找到个人优势 每个人都有...
    剽悍的大林阅读 143评论 0 0