Java多线程:解决高并发环境下数据插入重复问题

2023-11-15

1.背景描述


应用框架:Spring + SpringMVC + Hibernate 
数据库:Oracle11g

一家文学网站向我系统推多线程低并发推送数据,我这边观察日志和数据库,发现有一个作者被存储了2次到数据库中。按照程序的编写逻辑,重复的数据是会被判断出来不被存储的。

2.原因分析

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

if(用户不存在)
{
    xxxxx
    存储用户到数据库
}
else
{
    重复推送,不采取任何措施
}
这个操作还没有执行完毕,第二条拥有相同数据的线程已经进入并通过了if的检验,导致数据库存储了两条相同的数据。后来我自己写了个100并发的多线程测试程序,发现100条相同数据中有40条被插入到了数据库里!天啦噜!!!因此确定了是多线程的并发导致了程序的判断逻辑失效。

3.解决思路:

    1) 在Author主表中对 身份证号 添加了唯一索引,现在Author主表不会出现重复数据了,如果连续推送客户会收到一条推送失败的提示信息。

    2) 但是AuthorOrg表(Author与AuthorOrg是一对多关系)依然会出现重复数据,想过添加siteId + userUniqueId的 联合唯一索引来解决,但是想到work表也会出现同样的问题,添加过多索引会导致DB占用空间无限增大,因此不采用。

    3) 考虑使用synchronized对方法添加同步锁,但是这样会导致其他正常数据的推送线程也被阻塞,影响效率。因此不采用。

    4) 使用对数据库添加行锁,实验发现还是会出现2条重复数据
        分析:
            理论上的结果应该是1条成功,149条失败。
            对数据库的select语句添加行锁必须作用于某条记录,但是第一次报送时,数据库中并没有这条数据,因此行锁根本没有加上,导致第二条数据成功异步使用select语句。
            第一次报送成功以后,数据库中有了这条数据,select语句成功的对这条记录添加了行锁,所以后边不会出现重复数据。因此此法不可用。

    5) 即想提高效率不对方法添加synchronized,又想保证数据准确性,最后使用synchronized(siteId + uid) 在Controller层加锁(保证了只有重复数据被加锁,在Controller使用的原因是因为事务会在Service调用完毕才被提交,我实验过在Service同步,150并发会出现2条重复数据,因为事务还没来得及提交)
    测试结果:测试了3次150并发  不到一秒的时间全部返回,结果1条登记成功,149条返回该作者已登记。

下一步:
    针对所有可能出现高并发问的接口进行调整。

4.提示

    这种加同步锁的方法在负载均衡下的多台应用服务器会失效!因为就算Spring保证了对象是单例的,但是多台服务器肯定是多个对象!因此synchronized将无效。解决方法是在数据库层对该对接公司的唯一记录加select锁,这样就能保证数据的不重复性,但是会降低该公司推送数据的效率(相当于逐条推送),但是公司与公司之间还是并行推送的。还有一个方法就是将业务逻辑写入存储过程,然后对存储过程加锁,这种方法太麻烦了,需求有变动就必须去修改存储过程,但是效率要比前者高得多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java多线程:解决高并发环境下数据插入重复问题 的相关文章

  • java中synchronized关键字

    1 synchronized关键字简介 synchronized是java中的一个关键字 在中文中为同步 也被称之为 同步锁 以此来达到多线程并发访问时候的并发安全问题 可以用来修饰代码块 非静态方法 静态方法等 修饰代码块时 给当前指定的
  • JAVA多人聊天室(多线程基础聊天室可以私聊/群聊)

    创建一个类定义聊天的规则 package com test tcpmap 该程序定义了聊天的规则 public interface CrazyitProtocol 定义协议字符串的长度 int PROTOCOL LEN 2 下面是一些协议字
  • 【JavaEE初阶】第九节.多线程 (基础篇)定时器(案例三)

    作者简介 大家好 我是未央 博客首页 未央 303 系列专栏 JavaEE初阶 每日一句 人的一生 可以有所作为的时机只有一次 那就是现在 前言 一 定时器概述 二 定时器的实现 2 1 Java标准库 定时器的使用 2 2 自己模拟实现一
  • 多线程面试总结

    总结 每个对象有一个监视器锁monitor 线程进入同步方法时尝试获取monitor的所有权 其他线程进入阻塞状态 该线程释放monitor的所有权后其他线程重新尝试获取monitor的所有权 只能有一个线程对同步监视器加锁 1 多线程的问
  • Kafka 顺序消费方案

    Kafka 顺序消费方案 前言 1 问题引入 2 解决思路 3 实现方案 前言 本文针对解决Kafka不同Topic之间存在一定的数据关联时的顺序消费问题 如存在Topic insert和Topic update分别是对数据的插入和更新 当
  • 多线程实现事务回滚

    多线程实现事务回滚 特别说明CountDownLatch CountDownLatch的用法 CountDownLatch num 简单说明 主线程 mainThreadLatch await 和mainThreadLatch countD
  • Java 线程关闭

    Java线程关闭的方式 1 使用状态位 public class CloseThread extends Thread boolean flag true int index 0 Override public void run while
  • 主线程退出后,子线程会不会退出

    额 好吧 这是个标题党 其实所有的线程都是平级的 根本不存在主线程和子线程 下文所述为了方便 将在main函数中的线程看做主线程 其它线程看成子线程 特此说明 先考虑以下代码 include
  • 并发编程(二)——内存模型

    前言 欢迎大家一起来学习多线程 大家一起来学习吧 并发编程 一 多线程快速入门 并发编程 二 内存模型 并发编程 三 多线程之间如何实现通讯 并发编程 四 JUC并发包常用方法介绍 并发编程 五 线程池及原理剖析 并发编程 六 java中锁
  • [Java实现 Scoket实时接收Tcp消息 优化层层叠加]

    目录 前言 基础实现代码 描述 优化代码多线程处理客户端连接和消息接收 描述 再次优化异步实现 以下是使用 CompletableFuture 实现异步处理客户端请求的示例代码 描述 进一步优化的代码 Netty来实现Socket服务器 描
  • 多线程系列之——事件内核对象

    所有内核对象里面事件内核对象是最简单的一个 它包括一个使用计数 还有两个布尔值 一个布尔值用来表示事件是手动重置事件还是自动重置事件 另一个布尔值表示当前是否处于触发状态 当一个手动重置事件被触发的时候 所有等待该事件的线程都能变成调度状态
  • Java多线程(四):什么是死锁以及如何解决死锁

    目录 1 什么是死锁 2 死锁产生的原因 3 如何解决死锁问题 3 1 改变环路等待条件 3 2 破坏请求并持有条件 1 什么是死锁 死锁 是指两个或两个以上的进程在执行过程中 由于竞争资源或者由于彼此通信而造成的一种阻塞的现象 若无外力作
  • Linux系统编程:多线程交替打印ABC

    引言 分享关于线程的一道测试题 因为网上基本都是Java的解决方法 决定自己写一篇来记录一下线程的学习 问题描述 编写一个至少具有三个线程的程序 称之为线程 A B 和 C 其中线程 A 输出字符 A 线程 B 输出字符 B 线程 C 输出
  • C++多线程(并发、进程、线程的基本概念和综述)

    并发 进程 线程的基本概念和综述 并发 并发表示两个或者更多任务 独立的活动 同时发生 进行 例如 一面唱歌一面弹琴 一面走路一面说话 画画的时候听小说等 回归到计算机领域 所谓并发 就是一个程序同时执行多个独立的任务 以往计算机只有单核C
  • 线程池用例

    线程池逻辑类 public class TaskExecutorService private final ExecutorService pool private final ThreadPoolExecutor pool private
  • 阿里巴巴开发手册-并发处理

    强制 获取单例对象要线程安全 在单例对象里面做操作也要保证线程安全 说明 资源驱动类 工具类 单例工厂类都需要注意 强制 线程资源必须通过线程池提供 不允许在应用中自行显式创建线程 说明 使用线程池的好处是减少在创建和销毁线程上所花的时间以
  • Java线程(Thread)生命周期的6种状态

    当线程被创建并启动以后 它既不是一启动就进入了执行状态 也不是一直处于执行状态 在线程的生命周期中 可能处于不同的状态 java lang Thread State 列举出了这6种线程状态 线程状态 导致状态发生条件 New 新建 线程刚被
  • ScheduledThreadPoolExecutor周期定时任务异常处理踩坑的问题!!

    问题原因 在公司写项目的时候 有一个周期定时任务的需求 就想着阿里巴巴开发手册里不是说不能用Executors去创建线程池 因为存在如下问题 FixedThreadPool和SingleThreadPool 允许的请求队列长度为 Integ
  • 多线程案例:购买车票

    购票案例 多线程同步 多线程的并发执行虽然可以提高程序的效率 但是 当多个线程去访问同一个资源时 也会引发一些安全问题 并发 同一个对象被多个线程同时操作 处理多线程问题时 多个线程访问同一个对象 并且某些线程还想修改这个对象 这时候我们就
  • JUC的常见类

    目录 Callable ReentrantLock Semaphore CountDownLatch JUC 即 java util concurrent 其中存放了一些进行多线程编程时有用的类 Callable Callable是一个接口

随机推荐

  • ISP_matlab

    确定输入是否为结构体数组字段 MATLAB isfield MathWorks 中国 对话框打开文件 获取路径和文件名 file path uigetfile raw RAW fid fopen fullfile path file htt
  • 百度通用翻译api使用

    官方api文档 http api fanyi baidu com api trans product apidoc springboot demo地址 https github com Blankwhiter translate 第一步 注
  • python web界面模板_Python简单轻量级Web Server模块Bottle

    Bottle 提示 使用此WEB服务器模块需要有基本的HTTP知识 简单 轻量级指的是 上手不难 容易使用 模块不大还能完成一般Web服务器的功能 Bottle是Python平台的轻量级Web Server 准确的说是HTTP Server
  • node.js在idea里运行

    Node js 是一种运行在 Chrome V8 JavaScript 引擎上的基于 JavaScript 的客户端运行时 JavaScript runtime 它可以用于构建网络应用程序和服务 在 Node js 中 你可以使用多种构建工
  • 从数据库字符串中获取数字部分,用于数据分析

    目录 前言 一 思路 1 获取字符串中的小数及整数部分 代码 效果 解析 2 获取字符串中数字部分 代码 效果 解析 二 总结 前言 在大数据时代 我们经常要分析很多非结构化的数据 同时也要分析很多非标准的数据 如 0 78吨 CYJ23w
  • 【数据结构 001】 定义

    数据 能被计算机处理 能被计算机识别 能输入计算机 数据元素 有一定意义的基本单位 数据项 数据元素的组成单位 认为是数据结构中最小组成单位 数据对象 具有相同性质的数据元素的集合 数据结构 存在特定关系的数据的集合 数据之间特定的结构关系
  • 线性表(C++实现)

    线性表的定义与基本操作 定义 具有相同数据类型的n个数据元素的有限序列 n是表长 当n为0的时候线性表是一个空表 如果用L命名线性表 那么其一般表示为 L a 1
  • 山谷 蓝桥杯

    问题描述 给定一个字母矩阵 如果矩阵中的某个位置不在四条边上 而且该位置上的字母小于其上下左右四个位 置的字母 则称为一个山谷 例如 对于如下矩阵 DDDDD CADCE FFFFA 共有两个山谷 位于第二行第二列和第四列 请注意第二行第三
  • 计算机网络-----网络编程

    网络编程 实战 网络基础 1 什么是计算机网络 2 什么是网络编程 3 网络编程中的主要问题 4 网络通信要素 5 通信协议分层思想 IP和端口号 1 IP 1 1定义 1 2IP的分类 2 端口号 2 1定义 2 2端口号的分类 网络通信
  • [转]Datagridview中的数据很多,加载完数据后滚动条自动到最下边的方法

    this dataGridView1 FirstDisplayedScrollingRowIndex this dataGridView1 Rows Count 1 转载于 https www cnblogs com aooyu archi
  • svn checkout 报 ‘svn: E000061: 执行上下文错误: Connection refused‘

    问题 svn E170013 svn E000061 svn svn checkout https xxx xxx xxx xxx 9443 svn project xxx svn E170013 Unable to connect to
  • php校验密码js,JS的密码强度校验正则表达式(附代码)

    这次给大家带来JS的密码强度校验正则表达式 附代码 使用JS的密码强度校验正则表达式注意事项有哪些 下面就是实战案例 一起来看一下 最近一直在做通行证项目 里面的注册模块中输入密码需要显示密码强度 低中高 今天就把做的效果给大家分享下 代码
  • 再谈二维数组,二级指针

    首先注意一个事实 是一个运算符 称 为 下 标 运 算 符 亦 称 变 址 运 算 符 我觉得应该是变址取内容 p n 恒 等于 p n 我们不能简单把指针看成地址 不要忽略掉数据类型 也就是说一个指针包含两方面 一个是地址 一个是数据类型
  • Nutanix是超融合厂商?原来我们都误会了……

    Nutanix是一家超融合厂商吗 是 也不是 中国的很多用户在初次接触Nutanix公司时 它已经在全球的超融合市场上声誉鹊起 并且被奉为超融合的鼻祖 所以人们先入为主地认为 Nutanix就是一家超融合厂商 作为一个新的细分产品市场的领导
  • Vijava 学习笔记之(VirtualMachineCloneSpec)

    VirtualMachineCloneSpec 指定虚拟机克隆规范 NAME TYPE DESCRIPTION config VirtualMachineConfigSpec 指定虚拟机的配置信息 customization Customi
  • http://www.baidu.com/cb.php?,搜索引擎中文网站提交登陆入口(09年完整汇总)

    7 雅虎中国 等同于易搜 提交 http search help cn yahoo com h4 4 html 8 TOM提交提交 http search tom com tools weblog log php 9 alltheweb 提
  • 数据结构六大排序详解(插入排序、希尔排序、选择排序、冒泡排序、快速排序、堆排序)

    数据结构六大排序详解 插入排序 希尔排序 选择排序 冒泡排序 快速排序 1 排序的概念 2 数据结构五大排序 2 1 插入排序 2 2 希尔排序 2 3 选择排序 2 4 冒泡排序 2 5 快速排序 2 5 1 hoare版本 左右指针法
  • 手把手教你开发微信小程序自定义底部导航栏

    手把手教你开发微信小程序自定义底部导航栏 一 创建微信小程序 二 配置底部菜单 1 配置app json文件 增加底部菜单 三 增加自定义底部菜单 1 app json配置文件 tabBar 增加 custom true 2 添加导航图标
  • ethercard php_PHP如何通过编程在服务端验证以太坊签名

    以太坊有一个非常强大的JavaScript生态系统 有一些很棒的开源项目 比如ethereumjs util 它提供了一个用以太坊帐户签名的即插即用功能 JavaScript的一个缺点是 在许多领域 它带来了安全问题 一个这样的安全风险是显
  • Java多线程:解决高并发环境下数据插入重复问题

    1 背景描述 应用框架 Spring SpringMVC Hibernate 数据库 Oracle11g 一家文学网站向我系统推多线程低并发推送数据 我这边观察日志和数据库 发现有一个作者被存储了2次到数据库中 按照程序的编写逻辑 重复的数