当前位置:   article > 正文

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

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

写在前面

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

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

具体问题和解决方案

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

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

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

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

        那么需要注意的点是:

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

 
  1. @Transactional
  2. public List<对象> test(){
  3.         //其他代码省略。。。
  4.         save(新增插入数据库操作)
  5.         return select(查询刚新增的数据)
  6. }

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

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

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

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

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

    save(新增实现)

}finally{

        lock.unlock();

}

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

这样就搞定了

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/234716
推荐阅读
相关标签
  

闽ICP备14008679号