秒杀下单 -> 多线程超卖问题 -> 乐观锁解决(查询到的优惠券库存和实际数据库中优惠券库存是否相同) -> 存在卖不完的问题 -> 扣减库存时判断库存大于0即可 -> 一人一单问题出现 -> 用悲观锁synchronized
锁住用户id锁的内容是判断一人一单、扣减库存和创建订单的过程。-> 悲观锁在集群模式下失效问题 -> 引入分布式锁(setnx)成功解决一人一单问题
由于业务阻塞导致锁超时释放带来的锁误删问题 -> 删锁前判断当前线程id和锁的id是否相同 -> 为保障原子性将判断和删除逻辑放在lua脚本中执行,删除锁时通过execute()来执行lua脚本
基于setnx分布式锁存在1.重入2.不可重试3.超时释放4.主从一致性 -> 引入redisson
1.redis基于hash结构实现,代替自定义锁时的string结构,哈希结构保存了线程id和重入次数,如果发现锁以及被获取,则对重入次数+1,在释放锁时,每释放一次,重入次数-1,直到重入次数减为0。
2.当获取锁失败后利用pubsub功能来订阅等待锁的释放,如果其他线程释放了锁,则会发送消息通知释放锁成功,然后继续重试。
3.利用watchDog锁获取成功后会开启一个定时任务,每隔一段时间就会重置锁的有效期
秒杀优化 -> 将耗时较短的逻辑判断放到Redis中,例如:库存是否充足,是否一人一单这样的操作,只要满足这两条操作,那我们是一定可以下单成功的,不用等数据真的写进数据库,我们直接告诉用户下单成功就好了。将优惠券id、用户id、订单id存到阻塞队列中,然后后台再开一个线程(通过实现runnable方法),后台线程再去慢慢执行队列里的消息,这样我们就能很快的完成下单业务。