来,高手们来看看,高并发问题......

很奇怪的人 2018-10-27 09:06:14
小弟现在碰到一个问题,我写的一个程序会每隔一段时间向数据库插入一条数据。有他语言的程序也在向这个数据库的表插入数据。而且还是三个程序同时运行。运行的逻辑都是一样的。一个程序跑的时候没问题,但多个程序同时跑的时候就会出现重复的数据。每个程序都有判断是否存在这一条数据在插入。但没有效果,本来是有解决方案的,设一个在表里面设置一个唯一主键,但现在这种方案弃用,不能在表里面新增列,所以看各位大师有什么办法解决没?
...全文
921 51 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
特别剑 2018-11-19
  • 打赏
  • 举报
回复
引用 楼主 很奇怪的人的回复:
小弟现在碰到一个问题,我写的一个程序会每隔一段时间向数据库插入一条数据。有他语言的程序也在向这个数据库的表插入数据。而且还是三个程序同时运行。运行的逻辑都是一样的。一个程序跑的时候没问题,但多个程序同时跑的时候就会出现重复的数据。每个程序都有判断是否存在这一条数据在插入。但没有效果,本来是有解决方案的,设一个在表里面设置一个唯一主键,但现在这种方案弃用,不能在表里面新增列,所以看各位大师有什么办法解决没?
说个简单粗暴的方法,给这3个程序每个加上sleep,执行的时候让他睡的时间不同,将时间错开,你上述的判断是不是就可以生效了呢?说白了就是个队列谁先进库的问题,我考虑问题可能简单了,我只管大胆假设,然后去尝试。说的对请前辈们纠正我的思路,感谢你
小灰狼 2018-11-19
  • 打赏
  • 举报
回复
引用 48 楼 qq_31074335 的回复:
楼主这个问题由于三个进程同时插库的造成的,居然数据库表结构不让动,其他用php和c写的程序也不能动,那么你就只能在你的Java程序执行的时间上想想办法了,不让他们同时的并发执行,在加上你java程序中的数据入库前做一次查询判从就OK。比如,当你获取到数据后,放入redis缓存,等待2两分钟后,再把这批数据查询判重后再入库。总结就是和其他两个进程错开入库时间。


这样做只能保证你的进程写入数据时是完美的,但不能保证别的进程写入数据不会有冲突!
比如你在写入数据时,已经做得非常好,100%保证绝对没有重复。但等你完成写入之后,PHP、C进程又写入一条数据,它们可没有进行冲突检查,可能与你之前写入的数据有冲突!
小灰狼 2018-11-19
  • 打赏
  • 举报
回复
引用 40 楼 Yangyg_0818 的回复:
多线程可以解决可以封装成异步方法


引用 46 楼 qisoft1213 的回复:
也可是试着用线程同步锁实现


引用 45 楼 qisoft1213 的回复:
使用spring框架的AOP思想,在业务层进行事物控制就可以解决


多线程之间的配合只能局限于一个进程里,而楼主的另外两个程序根本就不是Java写的,它不是运行在同一个进程里,甚至不是运行在同一台机器上!
AOP 说到底,还是只在一个进程里折腾。但楼主的问题根本原因是进程级别的,别的进程管不了。
所以楼主的程序做得再好,但别的进程要违反规则,你拿它一点办法都没有!因为你的程序管不了人家!
所以推测一下,即使楼主的程序没有运行,只运行PHP和C两个进程,它们也同样会出现数据冲突!真出现这情况,怪不了楼主的Java程序了!

引用 42 楼 leq3915 的回复:
触发器吧,插入之前查询一次


引用 43 楼 FangYANYI 的回复:
搞个触发器自己去重


用触发器勉强可行:插入前检查是否已经存在,如果已经存在,则把已经存在的数据关键字段值进行修改,然后插入新数据!
但触发器一般不建议使用的
并且,楼主的数据库连表都不允许建一个,加触发器可以吗!



引用 49 楼 weixin_42701376 的回复:
[quote=引用 楼主 很奇怪的人的回复:]小弟现在碰到一个问题,我写的一个程序会每隔一段时间向数据库插入一条数据。有他语言的程序也在向这个数据库的表插入数据。而且还是三个程序同时运行。运行的逻辑都是一样的。一个程序跑的时候没问题,但多个程序同时跑的时候就会出现重复的数据。每个程序都有判断是否存在这一条数据在插入。但没有效果,本来是有解决方案的,设一个在表里面设置一个唯一主键,但现在这种方案弃用,不能在表里面新增列,所以看各位大师有什么办法解决没?

说个简单粗暴的方法,给这3个程序每个加上sleep,执行的时候让他睡的时间不同,将时间错开,你上述的判断是不是就可以生效了呢?说白了就是个队列谁先进库的问题,我考虑问题可能简单了,我只管大胆假设,然后去尝试。说的对请前辈们纠正我的思路,感谢你[/quote]

这个思路我倒觉得有可行性,但建议改一下:
建三个中间库,结构与目标数据库完全一样。然后C、PHP、Java分别向这三个中间库写入数据。再另写一个定时任务,延时一定时间,周期读取中间库的数据,再同步到目标库中。
不过这个方案实在是……无语!
qq_31074335 2018-11-18
  • 打赏
  • 举报
回复
楼主这个问题由于三个进程同时插库的造成的,居然数据库表结构不让动,其他用php和c写的程序也不能动,那么你就只能在你的Java程序执行的时间上想想办法了,不让他们同时的并发执行,在加上你java程序中的数据入库前做一次查询判从就OK。比如,当你获取到数据后,放入redis缓存,等待2两分钟后,再把这批数据查询判重后再入库。总结就是和其他两个进程错开入库时间。
很奇怪的人 2018-11-17
  • 打赏
  • 举报
回复
引用 45 楼 qisoft1213 的回复:
使用spring框架的AOP思想,在业务层进行事物控制就可以解决
麻烦你看下啊,PHP和C语言的我改不了,我的能改,怎么解决他们的?你先看清楚在回答啊。PHP和C的已经写好了,改不了了。
qisoft1213 2018-11-17
  • 打赏
  • 举报
回复
也可是试着用线程同步锁实现
qisoft1213 2018-11-17
  • 打赏
  • 举报
回复
使用spring框架的AOP思想,在业务层进行事物控制就可以解决
qq_43212346 2018-11-16
  • 打赏
  • 举报
回复
0.0 弱弱的提一嘴。参考一下乐观锁。不再之前查重 在insert后查重 然后delete掉重的可以么
FangYANYI 2018-11-16
  • 打赏
  • 举报
回复
搞个触发器自己去重
刘大神仙 2018-11-14
  • 打赏
  • 举报
回复
触发器吧,插入之前查询一次
£迷失 2018-11-14
  • 打赏
  • 举报
回复
这种方法也想到过。但不能用。因为其它的程序不是用JAVA做的 .而且也不能架设一个公用的服务器。所以这种问题是不是很无解
不慕y 2018-11-11
  • 打赏
  • 举报
回复
多线程可以解决可以封装成异步方法
  • 打赏
  • 举报
回复
引用 10 楼 weixin_42305671的回复:
新建一张表可以吗?可以的话,这个表就见一个主键就行,导入存量的主键数据

3个不同的程序先往这个新表insert,没出现主键冲突,再往工作表insert
为表创建一个触发器。如何,如果插入数据触发查询。之后去重,
  • 打赏
  • 举报
回复
引用 10 楼 weixin_42305671的回复:
新建一张表可以吗?可以的话,这个表就见一个主键就行,导入存量的主键数据

3个不同的程序先往这个新表insert,没出现主键冲突,再往工作表insert
主键不是自增的吗,怎么可能重复,如果三个数据源同时插入数据,会出现重复的现象吗?
Seven.Kindoms 2018-11-07
  • 打赏
  • 举报
回复
好点的办法当然是,利用redis做分布式锁来保证数据一致性。但如果其他系统完全不可控,最简单的办法,更改数据库的事务隔离隔离级别,只是对性能有影响。
kingmax54212008 2018-11-03
  • 打赏
  • 举报
回复
可以考虑用mycat做中间路由。
然后,在路由里做互斥了。 【现在有不能改C、php的话】

mycat也是java写。

很奇怪的人 2018-11-01
  • 打赏
  • 举报
回复
引用 10 楼 weixin_42305671 的回复:
新建一张表可以吗?可以的话,这个表就见一个主键就行,导入存量的主键数据 3个不同的程序先往这个新表insert,没出现主键冲突,再往工作表insert
新建个列都不行,还新建个表,没办法改PHP和C的程序
我爱下午茶 2018-11-01
  • 打赏
  • 举报
回复
引用 25 楼 小灰狼的回复:
看来楼主的问题是无解了

原因很简单,数据库结构不让动,C和PHP两个进程你管不了,而你的Java进程不过是数据库众多访问的客户端之一而已。
想要多个进程在处理数据时不发生冲突,就必须要几个进程的共同协作,现在你能动的只有你的一个Java进程,根本就是做不到的嘛!

所以,我问楼主,即使你的Java进程不启动,光跑PHP和C两个进程,也应该会有冲突,只不过出现冲突的机率会小一点而已。如果光跑PHP和C没有出现过冲突,就说明这两个进程之间有应对机制,楼主可以让你们老板去找PHP和C的提供者要资料。
看了一遍,你是正解~
ainiburuqusi 2018-10-31
  • 打赏
  • 举报
回复
有没有考虑过联合唯一索引
笨蛋girl 2018-10-31
  • 打赏
  • 举报
回复
重复数据是指?如果就一个字段不允许重复的话, 第一种方法:你可以在表中把这个字段设为主键(最好看下这个字段是什么类型的) 第二种方法:或者你可以把这个字段设成AK约束
加载更多回复(31)

81,122

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧