前言
hi,大家好,我是小面~
此篇文章由浅入深介绍秒杀的简单设计。现在我们做的各种项目中不少场景会用到抢购、秒杀,在大流量的前提下,将带领大家一起去研究一下如何去设计一个简单的秒杀(技术实现)。
前置知识储备:mysql,redis 。
正文
1.0秒杀版本:
业务流程:
1.用户点击下单
2.库存表商品库存数量-1,订单表新增一条用户
订单记录
存在的问题:1.一人一订单问题,在此版本下没有去限制下订单的数量,违背了秒杀的规则。2.没有去判断库存够不够 解决方案:我们在做库存表商品库存数量-1,订单表新增一条用户订单记录操作之前多一步,去查询该用户有没有下过订单。如果有则返回 该用户下过订单的信息,如果没有则正常走下订单的流程。同时需要去判断库存
1.1秒杀版本:
业务流程:1.用户点击下单2.去判断库存是否够,如果够去数据库查询订单表,是否有该用户的订单信息。如果不够则返回错误信息。 3.无订单则库存表商品库存数量-1,订单表新增一条用户订单记录。有订单则返回错误信息。
存在的问题:
1.超卖问题:
解决方案:
(先考虑单机情况)我们将使用sychronized锁去
锁数据库的操作。
1.2秒杀版本:
业务流程:
1.用户点击下单
2.(此时已经是sychronized锁内)查询用户有没有
下过订单,库存是否充足
3.若没有查询到信息,则扣减库存,增加订单记录。
若查询到了 则返回信息。
存在的问题:1.高并发情况下数据库压力大 解决方案:这个问题我们将使用redis缓解数据库压力
1.3秒杀版本:
此版本我们将订单信息与库存放入缓存 业务流程:1.用户点击下单2.redis.get(库存)<1,|| redis.get(用户id)不为空,则返回信息库存不足或者已经下过订单 3.redis库存-1,redis订单+1 4.mysql库存-1,mysql库存+1
存在的问题:此版本缓解了数据库压力。但由于一直是单机版本,所以接下来将考虑分布式的问题 解决方案:1.分布式情况,sychronized将无效 我们将采用redis分布式锁来锁操作
1.4秒杀版本:
在1.3的版本上加分布式锁 业务流程:1.用户点击下单 此处我们采用redisson.tryLock()上锁2.redis.get(库存)<1,|| redis.get(用户id)不为空,则返回信息库存不足或者已经下过订单 3.redis库存-1,redis订单+1 4.mysql库存-1,mysql库存+1 5.redisson.unlock()
此版本我们在分布式的情况下就不会出现问题了存在的问题:此时数据库和redis操作都是在一个线程里去执行,效率有些低 解决方案:我们还可以继续做优化 提升效率,采用redis消息队列
1.5秒杀版本:
此版本加入了reids阻塞队列 异步处理mysql任务业务流程:1.用户点击下单此处我们采用redisson.tryLock()上锁2.redis.get(库存)<1,|| redis.get(用户id)不为空,则返回信息库存不足或者已经下过订单3.redis库存-1,redis订单+14.开启redis阻塞队列 异步处理mysql库存-1,mysql库存+15. redisson.unlock()
总结
这就是一个简单的设计,你会了吗?
我是小面,感谢各位人才的:点赞、收藏和评论,我们下期更精彩!







