秒杀场景的设计思考
秒杀场景的设计思考
在学习Redis的之后,一个绕不开的话题就是秒杀系统的设计。本文将从下面👇🏻几个方面展开一下个人简单的理解:
- 秒杀场景的介绍
- 设计的核心思路
- 怎么限流、削峰、异步
- planB
- 总结
秒杀场景的介绍
秒杀场景是大家常说的高并发场景,但是实际上其与单纯的高并发还有一点不同,主要区别就是其流量来的猛增,几乎是一个垂直的增长,而非线性增长的并发。
其具有如下特点:
- 瞬时高并发
- 读多写少
- 不能超卖
设计的核心思路
在解决系统架构的问题上,我们设计可以参考三要和一不要的原则,从一些通用性的角度提高一些系统健壮性:
- 要:要减少请求数据量;要减少请求次数;要减少依赖
- 不要:不要有“单点”
要减少请求数据量:后台返回前台的数据一般分为动态数据和静态数据,对于秒杀场景,我们可以考虑动静分离,对于不怎么会变化的数据,我们可以用cache、cdn等手段来直接处理,避免对后端资源的占用;对于库存这样的动态数据,我们才真正的去调用关键的接口和服务器。
要减少请求的次数:减少请求数最常用的一个实践就是合并CSS和JavaScript文件,把多个JavaScript文件合并成一个文件。这种方式在服务端仍然是单个文件各自存放,只是服务端会有一个组件解析这个URL,然后动态把这些文件合并起来一起返回。
有些同学会感觉这个第二点和第一点不是冲突的吗?
第一点说要减少请求数据量,所以要使用动静结合,第二点又说要减少请求的次数,和第一点不是矛盾了吗?实际上确实有一些矛盾的地方,就看取舍了,不同场景的考虑不一样,在秒杀场景来说,动静分离的好处肯定是比 动静合并一起返回的带来的收益更大的。
要减少依赖:这点很好理解。我们在设计系统的时候在能满足需求和拓展性等能力的基础上,系统的架构约简单越好。此外,在架构设计的时候,我们必须要很好的梳理清楚系统的强弱依赖,这样才能在发生系统瓶颈或者异常的情况下及时定位到问题并解决。
不要有“单点” :在分布式的架构设计的时候,我们的一个大忌就是“单点”问题,而解决的方法就是一般来说就是服务无状态话。服务无状态之后,我们可以非常方便的进行服务的扩容和迁移等。当然,对于数据库这样保存数据的服务很难(没办法)做到无状态话,这时,我们一般会采用冗余备份等方法增强其可靠性。
如何防止瞬时高并发
主要三个措施:缓存预热、流量限制。
我们也可以从事前、事中、事后的时间轴的角度来理解:事前:缓存预热;事后:流量限制、以及一些常用手段(限流、削峰、异步);事后:并发较低,主要考虑对库存的一些处理。
-
缓存预热
我们可以对热点数据进行预热,热点数据就是指那些被秒杀的商品的一些信息。可以在秒杀开始之前将这些热点数据提前加载在缓存中。
对于提前并不能得知哪些数据是热点的情况,我们可以考虑进行一些动态的数据分析来获取热key,比如京东开源的hotkey框架。
-
流量限制
在秒杀场景中,我们最有可能出现性能瓶颈的地方是用于控制库存的DB,因此需要尽量控制进入DB中的并发量。
可以从两个角度考虑:非后端角度降低并发量 + 后端角度降低并发量。
非后端角度限制并发
非后端角度降低并发量指的是在流量打到后端处理秒杀的服务器之前就降低并发量,常见的角度为:
1.人为增加流程:比如说答题系统。答题系统的增加一方面来说由于人的答题速度不一致,一定程度上是分散了并发数量,另一方面来说也可以一定程度上防止用户使用作弊器的行为;又比如说前端通过限频降低并发数量,让用户点击的时候实际上不是每次点击都真正有效。
2.分层过滤:通过分层的措施,每一层减少一部分流量。如下图所示,真正访问到DB中的并发量相对于用户访问量来说已经是一个很少的比例了。
后端角度限制并发
后端限制并发就是一些通用的手段了,常见的有:
- 使用mq进行异步削峰
- 使用线程池限制并发数量
- 使用缓存(使用缓存当然要考虑一致性问题,在秒杀场景就是“超卖"问题,文章后面关于超卖|库存如何扣减会讨论)
补充
库存何时扣减
库存的扣减一般来说有3种时机:
- 下单时扣减库存:买家只要完成下单,立即减扣商品库存,这种方式实现是最简单而且也是最精准的,通常可以在下单时利用数据库事务能力即可保证减扣库存的准确性,但需要考虑买家下单后不付款的情况。
- 付款时扣减库存:卖家下单的时候不扣减库存,付款的时候才扣减库存。好处是不需要考虑下单不付款的库存回填的情况,坏处则是并发量大会出现大量用户能下单,但是付款无法完成(显示库存不足 )。
- 结合前2种方案,下单时保留一定时间的库存:下单的时候扣减库存,如果用户30min时间内没有完成付款,那么就释放库存,其它用户可以继续抢购。
可以结合平时网上下单的步骤想一下,我们下单需要哪几个步骤:1.点击下单;2.填写地址并付款。
根据在淘宝购买商品的经验,综合用户体验和实际架构,一般来说选择方案3。
关于超卖|库存如何扣减
库存是放在MySQL中进行处理的,因此库存扣减判断的最终参考指标是:利用数据库的本地事务机制进行对库存的减扣,比如使用 where 库存 >0不满足就回滚。
但是在实际的秒杀场景架构中,肯定是会引入 Redis这样的缓存。
在引入缓存之后,我们就必须考虑缓存的一致性问题,一个很有意思的一点是:在秒杀场景中一般来说我们不需要强保证缓存和数据库中关于库存数据的一致性。
即,我们可以允许一定量的在Redis这一层的“超卖”,Redis“超卖”后,超卖的请求的数量不会太大,这些数量可以交给MySQL进行处理。
上面一段中提到“这些数量可以交给MySQL进行处理”,那么究竟多少数据可以交给MySQL处理呢?
实际上这就体现出压测的重要性了,这些请求究竟并发量由多少,MySQL可以承载多少理论分析只能有个指导值,具体有多少必须跑一跑压测才知道!
planB
前面我们提到了很多关于秒杀场景的设计,包括如何减少后端压力、如何设计库存扣减等等来保证系统的高性能。
然而,无论再精细的设计也只能保证系统尽可能健壮,因此我们在设计的时候必须考虑高可用方案。
关于如何设计高可用的方案,就是一个比较复杂的话题了,而且需要根据不同的系统和性能指标要求有不同的取舍,这里大概列出需要考虑的方面:
-
防止单点问题
-
防止影响扩大:隔离
-
如何降级、熔断
总结
秒杀场景是一个高可用场景中的典型类型,其拥有:高并发、读多写少、严格数据保证(不能超卖)的特点。
首先的思路是降低直接打入DB的并发量,可以考虑分层降低流量和增加步骤等操作降低并发。
其次库存扣减时机和超卖问题也有很多值得讨论的地方。
最后,再复杂的设计也有可能发生意外,因此我们必须考虑高可用的方案(planb)。
此外,在实际的场景中,除了正常的请求之外,往往我们还要考虑一些其他东西,比如说:灰产、用户恶意锁单等情况。
主要参考:
- geektime专栏:06 | 秒杀系统“减库存”设计的核心逻辑-如何设计一个秒杀系统-极客时间
- 后端进阶:面试官问我:如何设计一个秒杀场景?-阿里云开发者社区
- 面试必备:秒杀场景九个细节-腾讯云开发者社区-腾讯云 , 这个方案很详细,但是讲的很乱,想了解细节可以看看
相关文章:
秒杀场景的设计思考
秒杀场景的设计思考 在学习Redis的之后,一个绕不开的话题就是秒杀系统的设计。本文将从下面👇🏻几个方面展开一下个人简单的理解: 秒杀场景的介绍设计的核心思路怎么限流、削峰、异步planB总结 秒杀场景的介绍 秒杀场景是…...
快速掌握Haproxy原理架构
文章目录 一、原理架构二、无负载均衡三、四层负载均衡的工作流程四、七层负载均衡工作流程五、基础属性mode 属性retries 属性maxconn 属性clitimeout 属性servtimeout 属性states uri 属性 一、原理架构 四层tcp代理:Haproxy仅在客户端和服务器之间双向转发流量&…...
基于Centos7.X系统端口占用处理
1、查看当前端口占用情况 使用 netstat 查看系统中占用的端口和相关的进程。 netstat -tuln 或者 ss -tnl 选项解释: -t 显示 TCP 连接-u 显示 UDP 连接-l 显示监听的端口-n 以数字形式显示端口号和 IP 2、具体进程的pid netstat -anp | grep <port_numb…...
MySQL的索引失效的原因有那些
1. 数据类型不匹配 详细说明:MySQL在比较不同数据类型的值时,可能会尝试进行隐式转换。如果这种转换导致了复杂度增加或无法直接利用索引,则会导致索引失效。 实例与解决方案: -- 错误示例:数据类型不匹配 select *…...
Java重要面试名词整理(十):Kafka
文章目录 Kafka简介相关概念Kraft集群 Kafka收发消息梳理客户端工作机制消费者分组消费机制生产者拦截器机制消息序列化机制消息分区路由机制生产者消息缓存机制发送应答机制生产者消息幂等性生产者消息事务 Kafka集群架构设计-Kafka的Zookeeper元数据梳理Leader Partition选举…...
内置ALC的前置放大器D2538A/D3308
一、概述 D2538A/D3308是芯谷科技推出的带有ALC(自动电平控制)的前置音频放大器芯片,最初产品为单声道/立体声收录机及盒式录音机而开发,作为录音/回放的磁头放大器使用;由于产品的高增益、低噪声及ALC外部可调的特性&…...
04-微服务02
我们将黑马商城拆分为5个微服务: 用户服务 商品服务 购物车服务 交易服务 支付服务 由于每个微服务都有不同的地址或端口,相信大家在与前端联调的时候发现了一些问题: 请求不同数据时要访问不同的入口,需要维护多个入口地址…...
Java中的this关键字详解:深入理解与应用
目录 一、this关键字的基本概念 二、this指代当前对象 示例: 三、this区分成员变量与方法参数 示例: 四、使用this()调用构造方法 示例: 五、使用this传递当前对象 示例: 六、this的其他注意事项输出结果: …...
2、C#基于.net framework的应用开发实战编程 - 设计(二、四) - 编程手把手系列文章...
二、设计; 二.四、制定设计规范; 编码规范在软件编程里起到了非常重要的作用,主要是让代码更加的规范化,更加的简洁,更加的漂亮,更加的能够面向对象显示。 以前那个系列就有发布C#的编码规范的文…...
设置首选网络类型以及调用Android框架层的隐藏API
在Android SDK中提供的framework.jar是阉割版本的,比如有些类标记为hide,这些类不会被打包到这个jar中,而有些只是类中的某个方法或或属性被标记为hide,则这些类或属性会被打包到framework.jar,但是我们无法调用&#…...
“Gold-YOLO:基于聚合与分发机制的高效目标检测新范式”
🏡作者主页:点击! 🤖编程探索专栏:点击! ⏰️创作时间:2024年12月26日8点00分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文源地址(有视频…...
神经网络-AlexNet
AlexNet是在2012年的ImageNet竞赛后,整理发表的文章,也是对CNN网络的衍生。 网络结构 AlexNet网络结构如下图所示,网络分为了上下两部分,对应两个不同的GPU训练,可以更好的利用GPU算力。只有在特殊的网络层后&#x…...
Hutool 发送 HTTP 请求的几种常见写法
最简单的 GET 请求: String result HttpUtil.get("https://www.baidu.com");带参数的 GET 请求: // 方法1: 直接拼接URL参数 String result HttpUtil.get("https://www.baidu.com?name张三&age18");// 方法2: 使用 HashMap…...
【Linux】进度条
本文中,我们来写一个进度条。 本文大纲: 写一个命令行版的进度条。 1.回车换行 2.缓冲区问题(本文不深究) 2.1测试代码 3.写一个什么样的进度条? version1 version2 回车换行 这俩不是一个概念&…...
【zookeeper核心源码解析】第四课:客户端与服务端读写的io核心流程
系列文章目录 【zookeeper核心源码解析】第一课:zk启动类核心流程序列图 【zookeeper核心源码解析】第二课:俯瞰QuorumPeer启动核心流程,实现选举关键流程 【zookeeper核心源码解析】第三课:leader与follower何时开始同步&#…...
强化学习蘑菇书笔记
绪论 强化学习就是一个智能体在一个不确定的环境中最大化它的奖励。智能体在一个环境中获取某个状态后,做一个动作,也称为决策,在环境中执行这个决策以后,会有一个奖励。尽可能多地获得更多的奖励。 强化学习概述 强化学习与监…...
《机器学习》——线性回归模型
文章目录 线性回归模型简介一元线性回归模型多元线性回归模型误差项分析一元线性模型实例完整代码 多元线性模型实例完整代码 线性回归模型简介 线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。 相关关系&…...
Linux(Centos 7.6)网卡信息没有了问题处理
1.问题现象 虚拟机打开后,使用ifconfig查看IP信息,虚拟机默认的网卡名称是ens33,ifconfig没有看到相关问题,远程连接工具Xshell也不能正常访问该虚拟机。 [rootnode1 ~]# ifconfig lo: flags73<UP,LOOPBACK,RUNNING> mtu…...
WEB攻防-通用漏洞-文件上传-js验证-MIME验证-user.ini-语言特征
目录 定义 1.前端验证 2.MIME验证 3.htaccess文件和.user. ini 4.对内容进行了过滤,做了内容检测 5.[ ]符号过滤 6.内容检测php [] {} ; 7.()也被过滤了 8.反引号也被过滤 9.文件头检测 定义 文件上传漏洞是指攻击者上传了一个可执行文件(如木马…...
mybatis-plus代码生成器
<!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><!--mybatis-plus-generator 生成器--><depende…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
