主题
面试速答(先看这里)
**一句话结论:**我们要实现秒杀的库存扣减,最重要的是两个点:1、抗更高的并发。
60秒标准回答:
上面两篇文章中,介绍过秒杀的设计,其中关于库存扣减这里,我们选择用 lua 脚本实现的高效的库存扣减,于是有人提出了疑问: 为啥不用Redis 的分布式锁,而要用 lua 脚本?
为啥不用不用分布式锁?其实答案就是没必要!
我们要实现秒杀的库存扣减,最重要的是两个点:1、抗更高的并发。 2、避免超卖 。 尤其重要的就是这个防止超卖,这也是我们加锁的目的
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**上面两篇文章中,介绍过秒杀的设计,其中关于库存扣减这里,我们选择用 lua 脚本实现的高效的库存扣减,于是有人提出了疑问: 为啥不用Redis 的分布式锁,而要用 lua 脚本?
- **要点2:**拿我们常用的 Redisson 分布式锁来说,如果用了 tryLock,不考虑 waitTime的合理性情况下,和 lua 脚本的执行也差不多,就是排队执行。
- **要点3:**但是, 如果我们用 lua 脚本,可以直接用利用他的原子性特性,在一个脚本中实现库存的检查、扣减等动作。
- **要点4:**那有人说,我先加分布式锁,然后再用 lua 脚本不行吗?
- **要点5:**而且, Lua 脚本是在 Redis 服务器内部执行,它直接操作内存中的数据,执行效率是非常高的。
**记忆锚点:**lua → Redis → Lua → 统的稳定性和数据一致性 → 啥不用不用分布式锁 → Redisson
易错提醒:
- 2、避免超卖 。
- 这样才能避免超卖!
加分表达:
- 拿我们常用的 Redisson 分布式锁来说,如果用了 tryLock,不考虑 waitTime的合理性情况下,和 lua 脚本的执行也差不多,就是排队执行。
- 但是, 如果我们用 lua 脚本,可以直接用利用他的原子性特性,在一个脚本中实现库存的检查、扣减等动作。
- 如果使用分布式锁,在不使用 lua 脚本的情况下,每次库存扣减操作都需要多次与 Redis 服务器通信(例如,加锁、读取库存、扣减库存、释放锁等)。
追问准备:
- 上面两篇文章中,介绍过秒杀的设计,其中关于库存扣减这里,我们选择用 lua 脚本实现的高效的库存扣减,于是有人提出了疑问: 为啥不用Redis 的分布式锁,而要用 lua 脚本?
- 为啥不用不用分布式锁?
- 那有人说,我先加分布式锁,然后再用 lua 脚本不行吗?
- 不就是脱裤子放屁吗?
典型回答
上面两篇文章中,介绍过秒杀的设计,其中关于库存扣减这里,我们选择用 lua 脚本实现的高效的库存扣减,于是有人提出了疑问:为啥不用Redis 的分布式锁,而要用 lua 脚本?
为啥不用不用分布式锁?其实答案就是没必要!
我们要实现秒杀的库存扣减,最重要的是两个点:1、抗更高的并发。2、避免超卖 **。**尤其重要的就是这个防止超卖,这也是我们加锁的目的。
拿我们常用的 Redisson 分布式锁来说,如果用了 tryLock,不考虑 waitTime的合理性情况下,和 lua 脚本的执行也差不多,就是排队执行。
但是,如果我们用 lua 脚本,可以直接用利用他的原子性特性,在一个脚本中实现库存的检查、扣减等动作。这样才能避免超卖!
如果使用分布式锁,在不使用 lua 脚本的情况下,每次库存扣减操作都需要多次与 Redis 服务器通信(例如,加锁、读取库存、扣减库存、释放锁等)。这不仅增加了网络延时,还增加了系统的复杂性。
而如果使用 Lua 脚本,所有操作可以在一次脚本执行中完成,这大大减少了网络传输时间和通信次数。
那有人说,我先加分布式锁,然后再用 lua 脚本不行吗?这。。。不就是脱裤子放屁吗?直接用 lua 脚本不就好了吗,因为利用 Redis 的单线程机制,Lua 脚本的执行本身就是串行化的。
而且, Lua 脚本是在 Redis 服务器内部执行,它直接操作内存中的数据,执行效率是非常高的。而且使用 Lua 脚本实现的话,我们可以将库存扣减的逻辑集中处理,不需要在应用层做额外的同步处理。这样可以使得应用层的代码更加简洁,易于维护。
而且,用分布式锁需要细致的管理,包括锁的设置、维护锁的存活时间、处理死锁问题等。如果锁没有正确管理,可能会导致死锁或者锁失效,进而影响系统的稳定性和数据一致性。