新增数据并发处理,避免重复数据插入

8 篇文章 0 订阅
7 篇文章 0 订阅

写在前面

        项目使用SpringBoot的多实例微服务

层级调用Controller -->Service-->Dao或者Mapper(Mybatis)

具体问题和解决方案

        最近在做一个模块的时候,有一个新增接口可能存在重复插入的问题

QA人为模拟两个人同时操作,具体做法是用两个手机登录同一个界面同时操作,这样就造成了重复插入,

在数据库层面,为了避免重复数据,我们可以建立唯一索引,但建立唯一索引后,程序就会抛出唯一性异常,需要捕获处理

因为是多实例(即部署多个节点)的微服务,所以解决重复问题不能用同步锁、局部锁(RetreenLock)的方式来处理,所以就考虑用分布式锁,因为项目中即成了Redis,所以第一个想到的就是用Redis分布式锁来处理,也确实解决了问题。

        那么需要注意的点是:

1、在Service实现类中,不能将查询和新增操作放在同一个方法中,因为同一个方法在同一个事务中,比如下面的模拟代码:

 
@Transactional
public List<对象> test(){

        //其他代码省略。。。

        save(新增插入数据库操作)

        return select(查询刚新增的数据)

}

上面这段代码的问题是,新增和查询都在一个方法中,只有方法之行完成后,事务才会真正的提交,那么在方法中查询到的数据很可能就是没提交过数据前的数据,所以查询出来的结果就是不对的

        那么正确的做法就是将save(新增)实现和select(查询实现)放在不同的方法中,在Controller层去分别调用,这样查询数据就能查到最新新增的数据,因为事务已经提交了

Controller层,将新增方法上锁,这里用到的是redis分布式锁,实现起来也非常的简单,但实用:

RLock lock = redissonClient.getLock(key);
try {
    lock.lock();

    可以在这里做个简单的查询

    save(新增实现)

}finally{

        lock.unlock();

}

然后在查询数据就能查询到最新保存的数据了,因为事务已经提交了

这样就搞定了

        当然也可以用其他的分布式锁,比如创建Zookeeper的临时节点来作为锁,

这里不太推荐用数据库锁,除非数据量非常小,用户量也少,操作不频繁。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值