分布式秒杀系统的设计
分布式秒杀系统的设计
前言
不知道你在面试的过程中有没有被问到如何设计一个分布式秒杀系统?本篇博客根据大神们的梳理的体系并结合自己实际的项目经验,大致描述我们在设计分布式秒杀系统需要关注的核心内容——分布式锁、分布式限流、消息队列等等,希望可以帮助同学们可以在面试中更加从容地回答这个问题。
正文
分布式秒杀系统的设计
秒杀系统的核心的问题
- 并发读:核心的优化理念是减少用户到服务端来“读”数据,或者让他们读更少的数据;
- 并发写:要求在数据库层面独立出一个库,做特殊处理,可以理解为为秒杀设计专门的表,精简表字段。
秒杀系统的的基本要求:
- 高性能:涉及大量并发读写,可以从缓存、消息队列、 请求削峰等角度进行设计
- 一致性:保证秒杀减库存中的数据一致性。
- 高可用:保证系统的高可用和正确性,设计
PlanB
进行兜底。
架构原则(4要1不要):
- 数据要尽量少:用户请求与响应的数据尽可能得少,可以减少数据序列化与反序列化的性能损耗;
- 请求数要尽量少:减少或者合并
css/java script
、图片,以及Ajax
请求等,TCP
三次握手,DNS
解析等都会有资源消耗; - 路径要尽量短:用户发出请求到返回数据这个过程中,需求经过的中间的节点数尽可能少,尽可能使用
RPC
调用,提升系统性能; - 依赖要尽量少:依赖,指的是要完成一次用户请求必须依赖的系统或者服务;
- 不要有单点:无论是系统资源还是数据资源在设计的时候一定要考虑冗余。
根据上述的,可以设计如下:
秒杀系统的实现:
- 分布式限流:采用
sentinel
的方式进行分布式限流,诸如warm up
(预热)、拒绝、匀速排队等手段; - 负载均衡:对系统进行微服务化,拆分成商品中心、用户中心、订单中心;
- 缓存的使用:对热点数据(遵循二八原则)并且对实时性要求不高的数据进行缓存处理,如商品的基本信息;
- 消息队列的使用:针对可以异步处理的操作,如下单,采用消息队列的方式进行处理, 实行流量削峰;
- 分布式锁:进行抢购时采用分布式锁的方式保证不会出现“超卖现象”;
如何防止“超卖”现象
秒杀系统防止的“超卖”的关键在于减库存的方式,通常有三种:
- 下单减库存:一定不会出现超卖情况,但是有些人下单完不付款会影响其他人。
- 付款减库款:付款减库存,可能会因为并发高导致付款时已经卖光,付不了款。
- 预扣库存:最常用,如下单后扣库存,保留十分钟,在十分钟内未付款就不保留。如果付款时发现库存不足则不允许付款。
预扣库存,存在“黄牛抢单”恶意抢单的情况,可以通过信誉积分、设置最大购买数、已有未支付订单不允许再次下单等方式进行控制,预扣库存通常使用分布式锁来实现的。
技术方案:
- 采用
setnx
的方式实现分布式锁,在获取锁,进行查库存 -> 创建订单 -> 扣减库存
(并不会对库存数量进行上锁),这种方案将实现请求的序列化,但是并发量有限 - 采用分段锁的方式进行抢购,可以借鉴
LongAdder
的实现,通过订购时随机分配一个分段锁,如果该分段库存不足,要自动释放锁,切换到一下分段库存尝试获取锁。 - 分布式锁不会保存库存数量,获取锁只是获取购买销售品的资格,库存数量由数据库控制。
如解决订单过期库存回库问题
解决订单过期库存回库的潜在方案:
- 使用后台线程不断扫描数据库,性能极低,弃用
- 将订单数据存入
Redis
中并设置失效时间,考虑到要保留订单信息,弃用 - 使用
delayedQueue
延时队列,设置到期时间,其中的对象只能在到期时才能从队列中取走,进行过期操作,但是不支持分布式,弃用 - 使用分布式定时任务去处理相关订单,但是时间间隔难以设置,并且数据量巨大,慎用
- 使用
RabbitMQ
延迟队列来实现,并使用定时任务处理可能的消息丢失导致的库存无法释放,采用
如何解决用户重复订购问题
用户重复订购可以理解为请求幂等性的实现:
- 使用数据库唯一键,在锁座表中,设定场次
Id
和座位Id
作为唯一键。锁定座位时,如果座位已经售卖,会报出数据库异常,不允许某一个座位重复售卖。 - 基于
Redis
来实现,使用set
操作具有天然的幂等性,当业务处理完再删除对应的key
- 通过先查一次数据,来判断是新增操作还是更新操作
- 通过向数据库前置一个布隆过滤器来判断数据是新数据还是旧数据,再使用主键索引来实现
- 使用状态机来保证幂等性,订单状态可以有初始化、订购中、订购失败、订购成功,从而限制重复订购
- 对于前端的订单采用
token
幂等性校验,防止重复点击或者网络原因导致重复提交,外部接口的请求采用外部订单号做幂等性校验 - 借助消息队列的串行化,借助第三方的幂等性校验,也能保证我们业务上的幂等性
关于系统的设计中涉及的技术可移步:
分布式锁可参考我的博客:从悲观锁、乐观锁到分布式锁
负载均衡等分布式知识可参考我的博客:溪源的Java笔记—分布式
消息队列可参考我的博客:溪源的Java笔记—消息队列
分布式限流可参考我的博客:高并发之限流算法
springboot实现商品秒杀功能可参考我的博客:springboot实现商品秒杀功能
分布式秒杀系统的设计相关推荐
- 面试必备:一个秒杀系统的设计思考
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:阿哲 segmentfault.com/a/11900000 ...
- 从构建分布式秒杀系统聊聊限流特技
前言 俗话说的好,冰冻三尺非一日之寒,滴水穿石非一日之功,罗马也不是一天就建成的.两周前秒杀案例初步成型,分享到了中国最大的同 性友网站-码云.同时也收到了不少小伙伴的建议和投诉.我从不认为分布式.集 ...
- 从构建分布式秒杀系统聊聊线程池
前言 从0到1构建分布式秒杀系统案例的代码已经全部上传至码云,文章也被分发到各个平台.其中也收到了不少小伙伴喜欢和反馈,有网友如是说: 说实话,能用上的不多,中小企业都不可能用到,大型企业也不是一个人 ...
- SpringBoot开发案例从0到1构建分布式秒杀系统
前言 最近,被推送了不少秒杀架构的文章,忙里偷闲自己也总结了一下互联网平台秒杀架构设计,当然也借鉴了不少同学的思路.俗话说,脱离案例讲架构都是耍流氓,最终使用SpringBoot模拟实现了部分秒杀场景 ...
- 一个秒杀系统的设计思考
简介:从架构视角来看,秒杀系统本质是一个高性能.高一致.高可用的三高系统.而打造并维护一个超大流量的秒杀系统需要进行哪些关注,就是本文讨论的话题. 秒杀大家都不陌生.自2011年首次出现以来,无论是双 ...
- 第一百一十一期:思考 | 一文说透秒杀系统如何设计
秒杀大家都不陌生.自2011年首次出现以来,无论是双十一购物还是 12306 抢票,秒杀场景已随处可见.简单来说,秒杀就是在同一时刻大量请求争抢购买同一商品并完成交易的过程.从架构视角来看,秒杀系统本 ...
- 经验:一个秒杀系统的设计思考
点击上方「蓝字」关注我们 前言 秒杀大家都不陌生.自2011年首次出现以来,无论是双十一购物还是 12306 抢票,秒杀场景已随处可见.简单来说,秒杀就是在同一时刻大量请求争抢购买同一商品并完成交易的 ...
- 一个秒杀系统的设计思考(整体思考,收藏了)
作者:阿哲 来源:https://segmentfault.com/a/1190000020970562 前言 秒杀大家都不陌生.自2011年首次出现以来,无论是双十一购物还是 12306 抢票,秒杀 ...
- 系统架构设计——秒杀系统架构设计
摘要 秒杀大家都不陌生.自2011年首次出现以来,无论是双十一购物还是 12306 抢票,秒杀场景已随处可见.简单来说,秒杀就是在同一时刻大量请求争抢购买同一商品并完成交易的过程.从架构视角来看,秒杀 ...
最新文章
- pyEcharts安装及详细使用指南
- vue 怎么全局到入常量_vue定义全局变量和全局方法的方法示例
- C#之自己定义的implicit和explicit转换
- 943c语言,考研备战:华南理工大学943计算方法(含C语言)复试大纲_跨考网
- 建立Windows Embedded Compact 7开发环境
- private用法 java_关于android开发中如何正确使用Private Services安全用法及代码示例...
- create CRM task via code
- PCM设备是做什么的? PCM作用是什么?
- 程序代码错误检测_错误检测代码
- 3000字长文剖析!企业大数据到底是什么,从哪来,怎么用?
- VB案例:DAO使用示例1
- 堆 堆栈 java_java的栈和堆
- PHP 8 中确认支持 JIT!
- 金鹰卡通java面试_两则电视栏目招募通告,来试试?!
- 详细解读TPH-YOLOv5 | 让目标检测任务中的小目标无处遁形
- python怎么算列表的平方_Python中排序形式的元素的平方列表
- 老男孩教育Linux50期远程控制连接
- RK3568替换开机logo界面
- 【科创人独家】爱因互动洪强宁:参与创业≠创业,融到钱的那晚我失眠了
- 网易再次下注10亿元,能在视频领域“砸”出水花吗