高并发下,数据重复插入,如何解决

具体描述如下,当有一条数据时,首先查询这条记录是否存在,存在则更新,不存在则创建,但是由于并发很高,导致数据重复创建。

加了唯一健索引,虽然数据不会重复,但是会报错,有没有好办法完美解决这个问题?

尝试了加锁,但是只有对数据更改有效,重复插入还是会出现,

使用redis记录状态,虽然缓存速度很快,但不是原子操作,更高并发下,还是会有问题。还有一个问题是,使用了事务,一旦回滚,还要删除缓存,维护起来麻烦

阅读 15.5k
12 个回答

还是加唯一索引,try catch捕获错误,判断错误错误码是否为唯一索引的错误码,如果是则跳过

mysql 的 replace into 了解一下。
可能 这个 会帮到你。

一、如果仅从解决问题来说replace into不错,其实也可以 insert ignore,这样可以忽略错误,因为你加了唯一索引,也能保证唯一插入
二、事务并不能解决高并发的问题,他解决的是原子性问题,保证了整个流程的完整性
三、如果是高并发情况下,redis是不错的解决方案了,在redis中加一个排它锁,当一个请求进来了先加排它锁,等sql执行完释放排它锁,redis的排它锁实现方式很多,比如用字符串set('lock',1),当lock为1的时候其就进入 while 循环,直到lock为0,
四、还有一个方案就是加乐观锁或者悲观锁,比如悲观锁:select id from XXX for update,但是这个和实际的业务逻辑有很大的关系,不知道你的业务逻辑适不适合表加锁的 方案

使用消息队列啊,可以保证每次只读取一条数据消息,redis可以用,但不成熟,可以使用activemq尝试下

存在则更新,不存在则创建这个场景可以使用一句SQL完成,具体可以百度一下,手头没有环境可以测试这个。

两个方案

1.INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; //插入一条数据,存在则更新,需要用到唯一索引
2.用redis的setNX命令

加锁redis悲观锁 setnx

redis是原子性的操作,你不要误导大家啊,避免数据重复加一个主键是比较保险的。

使用队列先进先出特性才是正解,讲sql的都是扯淡,高并发下都会有问题的

1:数据库唯一索引。
2:redis实现分布式锁(set NX EX 很多人都说不可靠,其实还是挺可靠的,公司很多项目用了,也没有出过什么问题),关于redis实现分布式锁安全的论证:https://mp.weixin.qq.com/s/JT...
3:基于ZooKeeper实现分布式锁。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏