面试总结20250425

Posted by WK on 2025-04-25
Estimated Reading Time 2 Minutes
Words 851 In Total
Viewed Times

问题背景

假设我们有一个秒杀系统,用户 A 只能购买一件商品。
如果没有分布式锁保护,在高并发场景下,可能会出现以下问题:

  • 用户 A 发起多个请求,由于并发处理,后端服务可能多次验证通过,导致用户 A 成功下单多次。
  • 数据库的唯一约束(如用户 ID 和订单状态)可能会延迟生效,导致短暂时间内产生重复订单。
    因此,需要一种机制来确保同一时间只有一个线程能够执行下单逻辑。

基于分布式锁实现一人一单

  • 加锁:
    • 在用户发起下单请求时,尝试获取分布式锁。
    • 锁的 key 通常是用户的唯一标识(如 user_id),例如:lock:user:{user_id}。
    • 如果获取锁成功,则继续执行下单逻辑;否则直接返回失败或等待重试。
  • 下单逻辑:
    • 验证用户是否已经下单(查询数据库或缓存)。
    • 如果未下单,则创建订单并更新状态。
  • 释放锁:下单完成后,无论成功还是失败,都需要释放锁。

锁的粒度

锁的 key 使用 user_id,确保每个用户的下单操作是独立的。
这种细粒度的锁可以避免不同用户之间的竞争。

锁的超时时间

  • 分布式锁需要设置一个合理的超时时间(如 5 秒),防止死锁。
  • 如果业务逻辑执行时间较长,可能需要延长超时时间,或者在业务逻辑中主动续期。

用户下单,redis 加锁 10min,程序 10min 都没结束会产生什么后果

  • 锁自动过期
  • 数据一致性问题
  • 系统资源耗尽,应为后续的请求迟迟得不到处理,导致系统资源耗尽,甚至系统崩溃。

如果 redis 锁 10 分钟后过期了,不让同一个用户下第二单,怎么实现(我说的存 mysql,然后删 redis)

在订单表中添加唯一约束,确保每个用户只能有一个订单记录。

redis 怎么设计 key,mysql 怎么设计表,让其记录一人下一单的情况

Redis Key 设计:

  • 格式:lock:user:{user_id}
  • 作用:用于分布式锁,确保同一时间只有一个线程能处理某个用户的下单请求。

MySQL 表设计

  • 表名:orders
  • 字段:
    • id:主键,自增。
    • user_id:用户 ID,唯一约束。
    • order_status:订单状态(如 0-未支付,1-已支付)。
    • created_at:创建时间。
    • 唯一约束:UNIQUE (user_id),确保每个用户只能有一条订单记录。免第二次下单,在 mysql 怎么设计有序订单 id(非简单递增),在 redis 里怎么设计数据结构

流程

  • Redis 加锁:lock:user:{user_id}。
  • 检查 MySQL 是否已有订单。
  • 如果无订单,插入新订单。
  • 释放 Redis 锁。

关键点

  • Redis 锁防并发,MySQL 唯一约束保数据一致性。
  • 锁超时时间合理设置(如 10 分钟),避免死锁。

MQ 怎么避免重复下单/ MQ 如何避免消息重复消费

  1. 生产者:消息幂等性
  2. 消费者:业务幂等性
  3. 唯一消息 ID
  4. 数据库:唯一约束

如果消息唯一标识不一样,消息内容一样,消费者怎么去重

  1. 基于消息内容的哈希值
  2. 实现消费的幂等性

If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !