背景:
众所周知,高并发情况下,对于库存的操作要格外小心,处理不当可能导致库存超扣,带来不必要的损失。
超扣原因:多并发一起读,发现库存均为1,然后各扣各的,最终库存为负。
方法:
1. 悲观锁:认为要超扣,提前防止
select num from product where xxx for update; 只允许单线程读取。
缺点:阻塞问题,导致其他线程等待
2.乐观锁:认为不会超扣,更新时再验证
update product set num = num - n where id=xxx and num > n; 保证减后得正值
优点:大量读情况,减少锁开销,提高系统吞吐量,
但并发很高。经常发生冲突重试则不如使用悲观锁
3.锁:比如redis锁,java synchronized
setNX(key, id, expireTime); 利用单线程redis的原子操作
优点 : 减轻mysql压力,性能快。
缺点:数据一致性,需要更多代码维护。可以采用双重缓存,或者队列补偿方式实现最终一致性
4.阻塞队列,仅适用于秒杀这种不连续请求的业务。将请求入队列,由单个消费者顺序执行。
缺点:局限于业务,不能实时反馈结果。