秒杀优化: 记录一次bug排查

现象

做一人一单的时候,为了提升性能,需要将原来的业务改造成Lua脚本加Stream流的方式实现异步秒杀。

代码改造完成,使用Jmeter进行并发测试,发现redis中的数据和预期相同,库存减1,该用户也成功添加了进去,但是打开数据库的订单表,发现这条数据没有添加进去。

排查

开始以为是consumer没有收到消息,检查了一遍队列名称,consumerGroup,consumer名称都是没问题的。

然后在子线程中打了断点,然后再次启动,发现报出了一个空指针异常,定位到了是创建对象createVoucherOrder2当中Long userId = UserHolder.getUser().getId()中user居然是空,token也没失效。

emmm,最后发现是createVoucherOrder2是在子线程中调用的,已经切换线程了,自然不能再从ThreadLocal里获取对象了。

队列中存在的订单对象中包含了userId,所以正确的做法应该是从订单对象里面取。

真的是一个很容易忽略的错误。

贴相关代码

        private void createVoucherOrder2(VoucherOrder voucherOrder) {
            //添加逻辑:该用户是否已经已经下过单了
            //防止黄牛恶意刷单 但是会存在和超卖相同的问题 同一个用户但是超卖了三张票
            Long userId = voucherOrder.getUserId();
            RLock lock = redissonClient.getLock("lock:order:" + userId);
            boolean tryLock = lock.tryLock();

            if (!tryLock) {
                log.error("不允许重复下单");
                return;
            }
            try {
                Long voucherId = voucherOrder.getVoucherId();
                //3.查询订单
                Integer count = query()
                        .eq("user_id", userId)
                        .eq("voucher_id", voucherId)
                        .count();
                //4.校验一人一单
                if (count > 0) {
                    log.error("无法重复下单");
                    return;
                }
                //5.库存扣减 超减问题并发量3000的情况下 超卖10张
                boolean success = seckillVoucherService.update()
                        .setSql("stock= stock -1")
                        .eq("voucher_id", voucherId)
                        .gt("stock", 0).update();

                if (!success) {
                    log.error("库存不足,下单失败");
                    return;
                }
                //6.添加订单
                voucherOrderService.save(voucherOrder);
            }catch (Exception e){
                log.error("下单失败{}",e.getMessage());
            }finally {
                lock.unlock();
            }
        }

emmm

再次启动,Mysql订单表成功添加一条数据。
在这里插入图片描述
Jmeter汇总报告
在这里插入图片描述

在这里插入图片描述

相关推荐

  1. 优化-基于阻塞队列实现优化

    2024-07-23 09:38:03       39 阅读
  2. 记录登录相关bug

    2024-07-23 09:38:03       58 阅读
  3. 记录kill不死的进程

    2024-07-23 09:38:03       57 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-23 09:38:03       106 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-23 09:38:03       116 阅读
  3. 在Django里面运行非项目文件

    2024-07-23 09:38:03       95 阅读
  4. Python语言-面向对象

    2024-07-23 09:38:03       103 阅读

热门阅读

  1. ArcGIS Pro SDK (九)几何 12 多面体

    2024-07-23 09:38:03       23 阅读
  2. 数据库连接池

    2024-07-23 09:38:03       27 阅读
  3. RKNN执行bash ./build-linux_RK3566_RK3568.sh 报错

    2024-07-23 09:38:03       25 阅读
  4. 数学建模--图论与最短路径

    2024-07-23 09:38:03       21 阅读
  5. mariadb安装在服务器(Linux)

    2024-07-23 09:38:03       26 阅读
  6. 银行卡二三四要素核验的多种应用场景

    2024-07-23 09:38:03       29 阅读
  7. 怎么在 Ubuntu 中卸载已经安装的软件

    2024-07-23 09:38:03       26 阅读
  8. ubuntu 源码安装postgis插件

    2024-07-23 09:38:03       29 阅读
  9. SpringCloud-Zuul-03

    2024-07-23 09:38:03       28 阅读
  10. uniapp picker-view 搜索选择框

    2024-07-23 09:38:03       26 阅读