流程
查询优惠券
判断券的库存
=》充足扣减 不足报错
超卖问题
只要在线程1扣减前查询,都会扣减
乐观锁性能比悲观锁性能好
版本号法
使用一个变量判断是否变化来判断 ==》利用库存代替版本
CAS
乐观锁弊端:成功率太低
==》对于库存问题:不用select相等,只要>0就行
==》对于必须相等的cas情况:分段锁,将100个库存分到10个表里面,到10个表里面分别去抢,成功率大幅度提高
一人一单
就是查询同个用户同张优惠券的订单是否存在
和库存超卖逻辑一样,大家都查询到为0
这里区别是判断数据是否存在,不是判断是否修改,只能用悲观锁
对整个流程抽象,对每个用户加锁
锁的释放时机
上面方法先获取事务再获取锁,锁释放后事务可能没有提交
先获取锁再提交事务,才能保证事务安全
事务是否生效
不懂spring
所以说这样逻辑实际变成了判断能不能买,有没有买过,能买的话在执行扣库存和下订单的操作 ==》double check库存是否真的能够减少
集群下的线程没锁住
每个JVM都有自己的锁,导致每个锁都有一个线程获取
分布式锁
考虑JVM外部的锁监视器
多进程可见
互斥:难点,必须保证只有一个人获取到,其他人都失败
常用的分布式锁
Redis分布式锁流程
锁超时误删
在删除时要判断下==》在存入时要存一个线程标识
分布式锁的原子性问题
判断锁标识和释放不是一起执行,没有保证原子性,删掉的锁不是自己的
用setnx实现分布式锁的缺点
可重入锁
保存一个访问的次数
hash结构没有set nx
获取锁流程
锁重试和watch dog
主从一致性问题 - 联锁
主节点的锁没有同步到从节点上
解决方法就是不用主从,建立多个独立的锁
只有在每一个节点都拿到锁才能成功??
这样宕机了一台获取锁就不会成功
Redisson总结
Redis优化秒杀性能
将两个不用更改数据库的操作独立处理
在redis中执行判断和扣减,异步的执行下单和减库存的操作
基于Redis完成秒杀资格判断
List模拟消息队列
拿出消息后消息发送时丢失了
PubSub的消息队列
三种通配符
天生阻塞且可以多个消费者拿到消息
基于stream的消息队列-单消费模式
基于stream的消费队列-消费者组
注意改ID就是从pendinglist中读
用ACK确认
功能完善