一人一单问题

java

运行

// 1. 获取当前登录的用户ID
Long userId = UserHolder.getUser().getId();

  • UserHolder:保存当前登录用户信息的工具类
  • 这行就是拿到:是谁在下单
  • 比如:用户 id = 101

java

运行

// 2. 去数据库订单表里查:
//    条件1:用户id = 当前登录用户
//    条件2:优惠券id = 这次要抢的券
int count = query()
    .eq("user_id", userId)      // 这个用户
    .eq("voucher_id", voucherId) // 这个优惠券
    .count();                   // 统计有几条订单记录

翻译成人话:

“去订单表里查一查,用户 101 有没有买过 优惠券 1001

买过几次?把次数给我统计出来!”

  • count 就是购买次数
  • 没买过 → count = 0
  • 买过 → count = 1 或更多

java

运行

// 3. 如果购买次数 > 0,说明已经买过了,直接拒绝
if (count > 0) {
    return Result.fail("用户已经购买过一次!");
}

  • 如果 count > 0 → 买过 → 拦截,不让买
  • 如果 count = 0 → 没买过 → 放行,继续下单

用生活例子讲明白

你去买限量优惠券

  1. 系统先看你是谁(拿用户 ID)
  2. 去订单本里翻:你有没有买过这张券?
  3. 买过 → 告诉你:不行,一人只能买一次
  4. 没买过 → 可以继续下单

这就是 一人一单

核心原理总结(3 句话背会)

  1. 拿到当前用户 ID
  2. 查数据库:这个用户 + 这个券 → 有没有订单?
  3. 有就拦截,没有就放行

⚠️ 重要提醒(面试 / 高并发必问)

你现在这段代码 单机没问题

但高并发下会失效!会出现一人买多单!

为什么?

  • 两个请求同时进来
  • 同时查数据库,都查到 count=0
  • 同时通过判断
  • 最后都下单成功

解决办法:加锁(分布式锁)

让同一个用户的请求,只能一个一个排队判断,就不会重复下单了。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务