秒杀商品设计
秒杀商品设计
前端限制
前端控制,不能重复点击
精简sql
典型的一个场景是在进行扣减库存的时候,传统的做法是先查询库存,再去update。 这样的话需要两个sql,而实际上一个sql我们就可以完成的。
可以用这样的做法: update miaosha_goods set stock =stock-1 where goos_id ={#goods_id}
and version = #{version} and sock>0 ;
这样的话,就可以保证库存不会超卖并且一次更新库存,还有注意一点这里使用了版本号的乐观锁,相比较悲观锁,它的性能较好。
同一个用户xx秒内重复请求直接拒绝
具体多少秒需要根据实际业务和秒杀的人数而定,一般限定为10秒。
具体的做法就是通过redis的键过期策略,首先对每个请求都从 String value = redis.get(userId) ;
如果获取到这个 value为空或者为null,表示它是有效的请求,然后放行这个请求。如果不为空表示它是重复性请求,直接丢掉这个请求。
如果有效,采用 redis.setexpire(userId,value,10).value
可以是任意值,一般放业务属性比较好,这个是设置以userId为key,10秒的过期时间(10秒后,key对应的值自动为null)
使用redis限流
限流的实现可以直接使用 Guava
的 RateLimit
方法,分布式的话,可以缓存在redis
中
使用redis加载商品,数据库乐观锁更新
- 将商品数据加载到
redis
- 用户进来查看
redis
中的库存数量num
,库存不足直接抛出 - 进入数据库,更新数据库库存(需要注意的是,这里要进行乐观锁判断,并且还要校验库存数量
num
,可以正好一起做乐观锁判断),不匹配也直接抛出 - 更新
db
后,更新redis
缓存
这里有一个乐观锁判断,如果一个线程
A
在走上面的流程,线程B
进入,查看到库存,在进入步骤3进行更新数据时,因为缓存中库存与数据库中的库存不一致,导致更新失败。
异步下单
为了提升下单的效率,并且防止下单服务的失败。 需要将下单这一操作进行异步处理。
最常采用的办法是使用队列,队列最显著的三个优点: 异步、削峰、解耦 。
这里可以采用rabbitmq,在后台经过了限流、库存校验之后,流入到这一步骤的就是有效请求。 然后发送到队列里,队列接受消息,异步下单。
下完单,入库没有问题可以用短信通知用户秒杀成功。 假如失败的话,可以采用补偿机制,重试。
服务降级
假如在秒杀过程中出现了某个服务器宕机,或者服务不可用,应该做好后备工作。 之前的博客里有介绍通过Hystrix进行服务熔断和降级,可以开发一个备用服务。
假如服务器真的宕机了,直接给用户一个友好的提示返回,而不是直接卡死,服务器错误等生硬的反馈。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2019-01-15 java中equals,hashcode和==的区别
2013-01-15 JavaScript 使用方括号([])引用对象的属性和方法 createDelegate
2013-01-15 JavaScript 弱类型