什么是流量削峰?如何解决秒杀等业务的削峰场景

文章推荐

1 作为程序员,开发用过最好用的AI工具有哪些?
2 Github Copilot正版的激活成功,终于可以chat了
3 idea,pycharm等的ai assistant已成功激活
4 新手如何拿捏 Github Copilot AI助手,帮助你提高写代码效率
5 Jetbrains的ai assistant已经激活成功,好用!

文章正文

流量削峰的由来

主要是还是来自于互联网的业务场景,例如,马上即将开始的春节火车票抢购,大量的用户需要同一时间去抢购;以及大家熟知的阿里双11秒杀, 短时间上亿的用户涌入,瞬间流量巨大(高并发),比如:200万人准备在凌晨12:00准备抢购一件商品,但是商品的数量缺是有限的100-500件左右。

这样真实能购买到该件商品的用户也只有几百人左右, 但是从业务上来说,秒杀活动是希望更多的人来参与,也就是抢购之前希望有越来越多的人来看购买商品。

但是,在抢购时间达到后,用户开始真正下单时,秒杀的服务器后端缺不希望同时有几百万人同时发起抢购请求。

我们都知道服务器的处理资源是有限的,所以出现峰值的时候,很容易导致服务器宕机,用户无法访问的情况出现。

这就好比出行的时候存在早高峰和晚高峰的问题,为了解决这个问题,出行就有了错峰限行的解决方案。

同理,在线上的秒杀等业务场景,也需要类似的解决方案,需要平安度过同时抢购带来的流量峰值的问题,这就是流量削峰的由来。

怎样来实现流量削峰方案

削峰从本质上来说就是更多地延缓用户请求,以及层层过滤用户的访问需求,遵从“最后落地到数据库的请求数要尽量少”的原则。

1.消息队列解决削峰
要对流量进行削峰,最容易想到的解决方案就是用消息队列来缓冲瞬时流量,把同步的直接调用转换成异步的间接推送,中间通过一个队列在一端承接瞬时的流量洪峰,在另一端平滑地将消息推送出去。

在这里插入图片描述

消息队列中间件主要解决应用耦合,异步消息, 流量削锋等问题。常用消息队列系统:目前在生产环境,使用较多的消息队列有 ActiveMQ、RabbitMQ、 ZeroMQ、Kafka、MetaMQ、RocketMQ 等。
在这里,消息队列就像“水库”一样,拦蓄上游的洪水,削减进入下游河道的洪峰流量,从而达到减免洪水灾害的目的。

2.流量削峰漏斗:层层削峰
针对秒杀场景还有一种方法,就是对请求进行分层过滤,从而过滤掉一些无效的请求。
分层过滤其实就是采用“漏斗”式设计来处理请求的,如下图所示:

在这里插入图片描述

这样就像漏斗一样,尽量把数据量和请求量一层一层地过滤和减少了。

如何解决秒杀等业务的削峰场景

什么是秒杀
秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大量用户前来抢购,并且会在约定的时间点同时在秒杀页面进行抢购。

秒杀系统场景特点

  • 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增。

  • 秒杀一般是访问请求数量远远大于库存数量,只有少部分用户能够秒杀成功。

  • 秒杀业务流程比较简单,一般就是下订单减库存。

秒杀架构设计理念
**限流:**鉴于只有少部分用户能够秒杀成功,所以要限制大部分流量,只允许少部分流量进入服务后端。

**削峰:**对于秒杀系统瞬时会有大量用户涌入,所以在抢购一开始会有很高的瞬间峰值。高峰值流量是压垮系统很重要的原因,所以如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的常用的方法有利用缓存和消息中间件等技术。

**异步处理:**秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。

**内存缓存:**秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大地提升。

**可拓展:**当然如果我们想支持更多用户,更大的并发,最好就将系统设计成弹性可拓展的,如果流量来了,拓展机器就好了。像淘宝、京东等双十一活动时会增加大量机器应对交易高峰。

架构方案

一般秒杀系统架构
在这里插入图片描述

设计思路
将请求拦截在系统上游,降低下游压力:秒杀系统特点是并发量极大,但实际秒杀成功的请求数量却很少,所以如果不在前端拦截很可能造成数据库读写锁冲突,甚至导致死锁,最终请求超时。
充分利用缓存:利用缓存可极大提高系统读写速度。

消息队列:消息队列可以削峰,将拦截大量并发请求,这也是一个异步处理过程,后台业务根据自己的处理能力,从消息队列中主动的拉取请求消息进行业务处理。

前端方案
浏览器端(js):

页面静态化:将活动页面上的所有可以静态的元素全部静态化,并尽量减少动态元素。通过CDN来抗峰值。

禁止重复提交:用户提交之后按钮置灰,禁止重复提交

用户限流:在某一时间段内只允许用户提交一次请求,比如可以采取IP限流

后端方案
服务端控制器层(网关层)
限制uid(UserID)访问频率:我们上面拦截了浏览器访问的请求,但针对某些恶意攻击或其它插件,在服务端控制层需要针对同一个访问uid,限制访问频率。

服务层
上面只拦截了一部分访问请求,当秒杀的用户量很大时,即使每个用户只有一个请求,到服务层的请求数量还是很大。比如我们有100W用户同时抢100台手机,服务层并发请求压力至少为100W。

**采用消息队列缓存请求:**既然服务层知道库存只有100台手机,那完全没有必要把100W个请求都传递到数据库啊,那么可以先把这些请求都写到消息队列缓存一下,数据库层订阅消息减库存,减库存成功的请求返回秒杀成功,失败的返回秒杀结束。

**利用缓存应对读请求:**对类似于12306等购票业务,是典型的读多写少业务,大部分请求是查询请求,所以可以利用缓存分担数据库压力。

**利用缓存应对写请求:**缓存也是可以应对写请求的,比如我们就可以把数据库中的库存数据转移到Redis缓存中,所有减库存操作都在Redis中进行,然后再通过后台进程把Redis中的用户秒杀请求同步到数据库中。

数据库层
数据库层是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担“能力范围内”的访问请求。所以,上面通过在服务层引入队列和缓存,让最底层的数据库高枕无忧。

1)分层过滤的核心思想

  • 通过在不同的层次尽可能地过滤掉无效请求。

  • 通过CDN过滤掉大量的图片,静态资源的请求。

  • 再通过类似Redis这样的分布式缓存,过滤请求等就是典型的在上游拦截读请求。

2)分层过滤的基本原则

  • 对写数据进行基于时间的合理分片,过滤掉过期的失效请求。

  • 对写请求做限流保护,将超出系统承载能力的请求过滤掉。

  • 涉及到的读数据不做强一致性校验,减少因为一致性校验产生瓶颈的问题。

  • 对写数据进行强一致性校验,只保留最后有效的数据。

最终,让“漏斗”最末端(数据库)的才是有效请求。例如:当用户真实达到订单和支付的流程,这个是需要数据强一致性的。

秒杀代码例子

//秒杀优惠券问题接
//接收数据token认证之类的操作
$body = array('couponCode' => 'kjt91000','uid' => 11
);
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
$redisName = $body['couponCode'];//优惠券编码
//根据业务判断是否可以重复秒杀,如果不可以取出数据去重
$hadSuccessArr = $redis->lRange($redisName,0, $redis->lLen($redisName));//获取已经秒杀到的id信息
foreach ($hadSuccessArr as $hadSuccess){//筛选
}//判断秒杀是否成功
if($redis->decr('secKill') >= 1){//判断用户能否秒杀和抢占秒杀名额,这两个操作必须是原子性的执行//秒杀成功$redis->rPush($redisName,$uid.'%'.microtime());echo $uid.'秒杀成功';
}else{echo '秒杀失败';
}$redis->close();

数据录入

/**PHP自学中心
** 2230304070@qq.com
**/
//数据写入库内操作 通过定时任务检索
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redisName = "kjt91000";
$length = $redis->lLen($redisName);
//判断数值是否存在
if($length){//从队列最左侧开始取出数值$user = $redis->lPop($redisName);//切割时间 uid$userArr = expload('%', $user);$addArr = array('uid' => $userArr[0],'time_stamp' => $userArr[1]);//保存到数据库中$res = $db->insert('redis_queue', $addArr);//如果失败,数据回滚 将数值重新放到list中if(!$res){//可以考虑 try catch 处理$redis->rPush($redisName, $user);}
}else{echo '没有需要插入的数据';
}//释放redis
$redis->close();

流量削峰总结

1.对于秒杀这样的高并发场景业务,最基本的原则就是将请求拦截在系统上游,降低下游压力。如果不在前端拦截很可能造成数据库(mysql、oracle等)读写锁冲突,甚至导致死锁,最终还有可能出现雪崩等场景。

2.划分好动静资源,静态资源使用CDN进行服务分发。

3.充分利用缓存(redis等):增加QPS,从而加大整个集群的吞吐量。

4.高峰值流量是压垮系统很重要的原因,所以需要Kafka等消息队列在一端承接瞬时的流量洪峰,在另一端平滑地将消息推送出去

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/14646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python设计模式02】设计原则

1.单一职责原则 单一职责原则(Single Responsibility Principle, SRP)是面向对象编程中SOLID原则的第一个原则。它强调每个类应该只有一个引起变化的原因,即一个类只负责一项职责。这一原则有助于提高代码的可维护性、可读性和可复用性。 单…

mysql锁表查看

命令 : show full processlist;//显示哪些线程正在运行

数字驱动,教育先行——低代码揭秘教育机构管理数字化转型

数字化时代为教育带来了许多变革和挑战,同时也为教育创新提供了无限可能。数字化转型可以帮助教育机构应对这些变革和挑战,提高教育效率和质量,满足学生个性化需求,优化教育管理和服务,并提高教育机构的竞争力。 并且…

docker 安装 yapi

文章目录 docker 安装 yapi一、拉取镜像二、创建目录三、添加配置文件四、初始化数据库表五、启动 yapi六、测试以及修改默认密码 没有 MongDB 的可以先看这个教程:MongDB安装教程 docker 安装 yapi 版本: 1.9.5 一、拉取镜像 docker pull yapipro/y…

以及Spring中为什么会出现IOC容器?@Autowired和@Resource注解?

以及Spring中为什么会出现IOC容器?Autowired和Resource注解? IOC容器发展史 没有IOC容器之前 首先说一下在Spring之前,我们的程序里面是没有IOC容器的,这个时候我们如果想要得到一个事先已经定义的对象该怎么得到呢?…

Flutter 中的 AnimatedSwitcher 小部件:全面指南

Flutter 中的 AnimatedSwitcher 小部件:全面指南 在 Flutter 中,动画是增强用户体验的重要工具。AnimatedSwitcher 是一个用于在两个 widget 之间执行平滑过渡动画的小部件。它可以自动处理两个状态之间的转换,提供丰富的动画效果。本文将详…

小白如何从零开始学新媒体运营三

最近有好多宝子私信问我是在哪里学习运营方面的相关知识的,那今天我就给大家整理了8个口碑较好的新媒体运营课程自学网站,帮大家快速入门新媒体运营. 1、考拉新媒体导航 实时热点、排版工具、运营干货、在线作图、高清图库、协作工具、数据平台&#xf…

三元组的最短距离

前言 个人小记 一、简介 定义三元组(a,b, c)(a,b,c 均为正数)的距离 D|a-b||b-c||c-a|。给定 3 个非空整数集合 S1, S2 ,S3, 按升序分别存储在 3 个数组中。请设计一个尽可能高效的算法,计算并输出所有可能的三元组&…

131. 面试中关于架构设计都需要了解哪些内容?

文章目录 一、社区系统架构组件概览1. 系统拆分2. CDN、Nginx静态缓存、JVM本地缓存3. Redis缓存4. MQ5. 分库分表6. 读写分离7. ElasticSearch 二、商城系统-亿级商品如何存储三、对账系统-分布式事务一致性四、统计系统-海量计数六、系统设计 - 微软1、需求收集2、顶层设计3、…

【Django】从零开始学Django(持续更新中)

PyCharm的版本必须为专业版,社区版不具备Web开发功能的。 一. Django建站基础 Django采用MTV的框架模式,即模型(Model)、模板(Template)和视图(Views),三者之间各自负责不同的职责。 ●模型:数据存取层,处理与数据相关…

【网络】cookie

cookie 的组成 cookie是浏览器中特有的一个概念,它就像浏览器的专属卡包,管理着各个网站的身份信息。 每个cookie就相当于是属于某个网站的一个卡片,它记录了下面的信息: key: 键,比如「身份编号」value: 值&#x…

vivado Miscellaneous Net-Related Constraints

Miscellaneous Net-Related Constraints KEEP Applied To Nets Constraint Values • TRUE • FALSE UCF Example net x_int KEEP TRUE; XDC Example set_property DONT_TOUCH true [get_nets x_int] SAVE NET FLAG Applied To Nets Constraint Values N/A …

Element-UI快速入门指南

一、引言 在前端开发领域,Vue.js以其简洁的API和灵活的组件系统受到了广泛的欢迎。Element-UI则是一套基于Vue.js 2.0的桌面端组件库,它提供了丰富的组件和友好的API,帮助开发者快速构建出美观且功能强大的Web应用。本文将带你快速入门Eleme…

信号:MSK调制和GMSK调制

目录 一、MSK信号 1. MSK信号的第k个码元 2.MSK信号的频率间隔 3.MSK信号的相位连续性 3.1 相位路径 3.2初始相位ψk 4.MSK信号的产生 原理框图 5.MSK信号的频谱图 二、高斯最小频移键控(GMSK) 1.频率响应 2.GMSK调制产生方式 2.1 高斯滤波器法 2.2 正交调制器法…

海外私人IP和原生IP有什么区别,谁更有优势?

一、什么是海外私人IP?什么是原生IP? 1、海外私人IP: 海外私人IP是由专门的服务提供商提供的IP地址,这些IP地址通常与特定地理位置或国家相关联。这些IP地址独享私人而不用与其他用户共享。海外私人IP广泛应用与跨境电商中&#x…

【Qt】修改QToolButton图标颜色

1. 目的 修改QToolButton的图标颜色,单一颜色,效果类似于Qt Creator左边选项卡。 2. 代码 QIcon MainWindow::setIconColor(QIcon icon, QColor color) {QPixmap pixmap icon.pixmap(QSize(64,64));QPainter painter(&pixmap);painter.setCompo…

DockerK8s

Docker&K8s 1. Docker 1.1 Docker是什么 用于构建容器化平台的软件,进程管理软件,主要用于部署应用程序并守护应用进程。容器是由docker软件启动的业务集成,该进程由docker全权管理。容器是进程,由内核机制来完成容器隔离。…

汇编:函数以及函数参数传递

汇编语言中的函数(或过程)是指一段可以被调用和执行的代码块;它们用于组织和重用代码,并使程序结构更加清晰;由于汇编语言没有高层次语言的语法糖,编写和调用函数涉及直接的堆栈操作和寄存器管理&#xff1…

c++网络开发笔记

1、第一节 1、阻塞模型 2、非阻塞IO 1)忙等待 2)IO复用模式(select,管理多个文件描述符号) 3)信号驱动IO,通过信号的方式 4)异步模型aio_read 3、select模型 int select(int nfds, fd_set *readfds, fd_set* writefds,fd_set* exceptfds, struct timeval* timeout);n…

Docker打包nginx镜像丢失挂载的配置文件

一般来说,Docker镜像构建过程中,如果没有正确地将配置文件复制到镜像中,那么在运行容器时就会丢失挂载的配置文件。 所以有2种解决办法: 第一种: 将挂载在宿主机上的配置文件复制到镜像中,可以参考这位老铁的文章《D…