秒杀活动防止超卖用 redis 做分布式锁,一个线程获得锁再执行业务代码,另外一线程获取锁怎么实现排队?
回答·37
最热
最新
- 秒杀活动怎么能限制同一时间只能有一个线程执行业务代码呢,redis 应该维护一个同步变量(商品数量),每次有请求过来就对变量减 1,只要不小于 0 则可以生成订单,生成订单失败则变量加一,小于 0 表示商品卖完了,变量加一。并发的问题交由接口层面去考虑
- 防止超卖可以用数据库的乐观锁,不用加分布式锁,影响性能
- 这做法效率低下,不合适做秒杀。 简单的方法可以在 Redis 里维护虚拟库存,用原子性减操作来判定是否超卖。如果实例单量小可以在订单生成期间加一层数据库的库存检验和递减,如果单量高可以考虑在 redis 中维护初步检验通过的订单信息,支付等操作直接针对内存,用消息延迟队列异步去检查订单状态,并同步致数据库
- 每个线程加锁时需要携带自己线程的标识,加锁用 lua 脚本实现,在 lua 脚本中加锁失败把线程标识存到 list 里然后返回失败,线程收到失败信息后到 Redis 轮询 list 第一位,看是否为自己标识,如果是自己则再尝试加锁。同时加锁 lua 中在执行加锁前也需要判断 list 是否为空,非空则将当前请求线程标识加到 list 最后,并返回加锁失败。 逻辑和 AQS 实现公平锁类似。
- redis 是原子性的,把“量”放进去,就不用管了,业务用不用队列和多线程是无所谓的
- 取决于 redis 的 io 多路复用模型
- 做个队列就可以了,等任务做完了自动通知
- 可以使用 aop 的形式,然后做一个通知事件的处理
- 可以用 redission 的读写锁,多个线程读的时候可以共享一把锁,但是写的时候只能有一个线程成功,这样可以很大的提高系统的并发能力。
- 自旋锁:如果获取不到锁,在规定时间一直尝试获取锁,redisson 有自旋锁实现。 还有的话可以设置一个队列,如果锁被使用,就进入队列等待,队列可以设置一个最大值,超过等待队列的最大值就直接失败。队列要实现先进先出