Redis 是一个开源的内存数据结构存储,它是一个独立的数据库/缓存服务

Redisson 是一个基于 Redis 的 Java 客户端框架,它在 Redis 基础上提供了分布式对象和服务

面试官,我是这样解决优惠券超卖的:

1. 核心思路:用Redis的SETNX命令实现分布式锁
2. 具体做法:
   - 用户领取优惠券时,先生成一个锁的key,比如:`coupon:lock:1001`
   - 用`SET lock_key user_id NX EX 10`命令尝试获取锁
     - NX:只有锁不存在时才能设置(互斥)
     - EX 10:10秒后自动过期(防止死锁)
   - 这个命令是原子的,保证设置值和过期时间一起完成
   
3. 业务处理:
   - 如果拿到锁,就查询库存、扣减、发券
   - 如果没拿到锁,直接返回"系统繁忙"
   
4. 锁续期:
   - 启动一个看门狗线程,每隔几秒给锁续期
   - 保证业务执行时间不会超过锁的过期时间
   
5. 释放锁:
   - 业务完成后,删除这个key释放锁
   - 用Lua脚本保证原子性,只删除自己的锁

这样就能保证同一时间只有一个线程能操作库存,不会超卖。

**面试官,我在项目中用Lua脚本实现分布式锁,主要解决三个问题:**

1. **获取锁的原子性**:
   - 用Lua脚本把SETNX和EXPIRE放在一起执行
   - 保证设置锁和设置过期时间是原子的
   - 脚本:`if redis.call('setnx', key, value) == 1 then redis.call('expire', key, expire)`

2. **释放锁的安全性**:
   - 用Lua脚本检查是否自己的锁,然后删除
   - 避免误删别人的锁
   - 脚本:`if redis.call('get', key) == value then return redis.call('del', key)`

3. **看门狗续期**:
   - 用Lua脚本给自己的锁续期
   - 保证业务执行时间不会超过锁过期时间
   - 脚本:`if redis.call('get', key) == value then return redis.call('expire', key, expire)`

**为什么用Lua**:
- Redis执行Lua脚本是原子的,不会有竞态条件
- 网络开销小,一次网络往返执行多个命令
- 逻辑都在服务端执行,更可靠

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐