美文网首页
从结算业务 深入理解 并发,mysql 乐观锁,可重复读

从结算业务 深入理解 并发,mysql 乐观锁,可重复读

作者: 川流不息attitude | 来源:发表于2022-09-29 18:36 被阅读0次

    从结算业务 深入理解 并发,mysql 乐观锁,可重复读

    结算 一般就是 ,把一些未结算的订单 金额,周期性的 结算 到 对应的账户 表里面去。

    一般就是 通过定时任务 分批跑,比如每个月 几号 结算一次 给供应商。

    思路一:

    根据条件

    while(true){

    // 查询一批数据处理

    // 满足条件 break

    // 处理业务 更改账户 ,记录流水,更改一批状态

    }

    思路一 存在的问题:

    可能会死锁:

    模拟:更改账户 一般都会使用乐观锁 ,改成功 就记录 流水 更改一批数据的状态。

            假如刚好 并发操作账户 (就会有一批数据没有处理),那么由于 mysql 5.6 以后隔离级别是可重复 读,所以就会 一直查询到那批数据未处理,而账户表又是 乐观锁 ,由于可重复读 导致版本号 一直读的不是最新的。所以就卡在这里了,很好模拟出来。
    

    思路二

    for(i=1;i<=totalPage,i++){

    // 一页页处理

    //处理业务 更改账户 ,记录流水,更改一批状态

    }

    思路二存在问题

    分页处理完成后 ,乐观锁操作账户 会出现一批数据未处理 。

    分页只能当前页只能是第一页,不能是 i ,因为处理完成后 状态变化,分页数据就不对了 会跳过一些数据。

    思路三

    相对比较完美 解决 并发场景,且能保证所有数据全部处理一边,不会漏掉数据。

    for(i=1;i<=totalPage,i++){

    // 一页页处理

    // 固定 当前页 为 1

    //处理业务 更改账户 ,记录流水,更改一批状态 ,记录有没有发生并发操作。

    }

    // 循环完成后,判断是否发生了并发,因为并发 就会存在 数据未处理

    // 存在并发 就在使用 可调度线程池 在调度 一下结算 逻辑

    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

    
    scheduledExecutorService.schedule(()->{
     log.info("重跑任务");
    },20,TimeUnit.SECONDS);
    

    写好程序 不简单,并发场景下 会出很多问题,处理的好,得加深 知识的理解。

    相关文章

      网友评论

          本文标题:从结算业务 深入理解 并发,mysql 乐观锁,可重复读

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