美文网首页
乐观锁高并发写数据出现的问题(springboot)

乐观锁高并发写数据出现的问题(springboot)

作者: n油炸小朋友 | 来源:发表于2020-05-13 17:23 被阅读0次

一、场景:

多条mq消息同时被集群接收处理,需要修改的数据有设计行的乐观锁,由于业务问题,修改数据库同一行数据的时间总是会刚好撞上。

二、条件限制:

乐观锁本来是适用于读大于写的情况,这里写的并发很高,本来是不适用的,但是因为框架问题,不能改这个乐观锁的设计,所以我想出了如下的方案。

三、方案a:重试+随机睡眠

1. 失败重试

乐观锁检测版本号,多个并发修改只会成功一个,这里每条数据都不可丢弃,所以加上失败重试。此外,由于是同步另一套数据,为了提高响应,所以这里也做了异步处理@Async。

springboot重试的注解使用可以参考:
https://blog.csdn.net/weixin_34138139/article/details/91876530

@Async
@Retryable(value= {ActivitiOptimisticLockingException.class}, maxAttempts = 5, backoff = @Backoff(delay = 1000L, multiplier = 3))
public void func(...) {
        // do ...
}
@Recover
    public void recover(ActivitiOptimisticLockingException e) {
        e.printStackTrace();
        log.info("-");
    }

需要注意的是重试方法和重试失败的回调方法返回值需要一致,异步方法的返回值也很特殊,这里不做介绍。
还有@Async、@Retryable的注解是靠代理类做增强的,如果非要本类调用需要创建或注入实例,或者干脆写到另一个类中去。

2. 随机数睡眠避开扎堆

类的属性增加:

private Random random = new Random();

生成随机数的方法:
我需要睡眠时间在0-3秒,所以这里private static final Integer SLEEP_MILLIS = 3000;

private Long getRandom() {
        long timeMillis = System.currentTimeMillis();
        int i = random.nextInt();
        Long l = timeMillis / i % SLEEP_MILLIS + 1;
        if(l < 0) {
            l = getRandom();
        }
        return l;
    }

在重试的方法里加上:

Long random = getRandom();
Thread.sleep(random);

四、改进,方案b:redis分布式锁 + 重试

需要注意的是,上面的设计有限制,mq消息先后顺序影响结果的就不适用。
有先后顺序的mq消息,被随机数睡眠调整了顺序,可能就会导致错误的结果。
虽然项目中消息的先后顺序并不影响结果,但是处理的时间变长了,最后采用redis分布式锁 + 重试的方案。

相关文章

  • 乐观锁高并发写数据出现的问题(springboot)

    一、场景: 多条mq消息同时被集群接收处理,需要修改的数据有设计行的乐观锁,由于业务问题,修改数据库同一行数据的时...

  • 乐观锁和悲观锁

    1.乐观锁和悲观锁的概念 乐观锁:假设不会发生并发冲突,数据库的并发操作只在提交的时候检查数据的完整性,并发效率高...

  • 锁从宏观上分为悲观锁与乐观锁 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时...

  • [091]技术-乐观锁探讨

    背景 乐观锁普通用在OLTP系统中就解决高并发问题,乐观锁如果用的不好出现错位的时候,定位时间一般都比较久(通常你...

  • MySQL数据库的锁机制

    在并发访问情况下,很有可能出现不可重复读等等读现象。为了更好的应对高并发,封锁、时间戳、乐观并发控制(乐观锁)、悲...

  • 乐观锁和悲观锁各自应用场景

    乐观锁 乐观锁是一种乐观思想,即认为 读多 写少,遇到并发写的可能性低,每次去拿数据的时候都 认为别人不会修改 ...

  • 乐观锁和悲观锁

    乐观锁悲观锁的使用背景 为了在高并发的情况下,也可以保证数据的准确性,也就是并发控制。 并发控制:确保当前用户和其...

  • 乐观锁与悲观锁

    乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会...

  • JAVA锁

    乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会...

  • 数据库的各种锁(乐观锁,悲观锁等等各种锁)

    我们才操作数据库的时候,可能会因为并发问题一起一系列的数据不一致的问题(数据冲突)这时就需要锁了, 乐观锁 乐观锁...

网友评论

      本文标题:乐观锁高并发写数据出现的问题(springboot)

      本文链接:https://www.haomeiwen.com/subject/qaunnhtx.html