高并发业务下的无损技术方案设计

news2024/11/14 3:48:43

0 前言

秒杀,既有需求真实且迫切的用户,也有试图牟利的黄牛。系统挑战,就是相较于以往千倍万倍的用户规模,可能是真人可能是机器人,在同一瞬间对系统发起冲击,需要海量的计算资源才能支撑。

秒杀系统的设计套路往往适用于其他高并发场景,具有较高的借鉴价值。同时,其特殊的挑战和需求,需要架构师在设计中权衡考量,这也有助于培养个人在权衡取舍方面的能力。

1 无损技术方案

好比治水:

  • 分流,让支流分摊压力,隔离风险。软件设计就是系统隔离,分割流量

  • 建水库存储洪水,再缓慢排出,削峰填谷。软件设计就是无损消峰

  • 拓宽河道,清除淤沙提高水流流速。软件设计就是性能优化,如多级缓存,特定场景的高性能库存扣减

一个请求打到服务器的基本链路:

DNS->网关->前端/后端

流量峰值也应该逐层减少:

1.1 系统隔离

秒杀活动因其高峰值特性,一般把它隔离出来成一个独立的秒杀系统(常规服务都是按领域特性做纵切,但这里按品类做横切,带有秒杀活动标的商品将会分流到独立的秒杀系统集群)。

考虑到交易系统体量很大,若为秒杀品类把整个交易系统复制一份,成本过大。所以把隔离区分为物理隔离和逻辑隔离:

  • 需定制化逻辑的能力和有特殊非功能性要求的能力剥离出来做物理隔离
  • 标准化且没有特殊非功能要求的能力采用逻辑隔离
部署架构图

先采用独立的秒杀域名和nginx集群(物理隔离)。这样:

  • 可以隔离流量大头,防止峰值冲击交易系统(非功能性需求)

  • 灵活扩展,针对不同时段的流量预估扩展nginx及后边服务的规模(非功能性需求)

  • 灵活增减私有的防控逻辑,而不影响原交易系统(定制化逻辑)

接着,将商详页和下单页独立部署(前端+BFF,物理隔离)。基于秒杀活动的玩法特征,海量用户在活动快开始时会反复刷新商详页,在活动开始时又会瞬时并发到访问下单页,所以这俩页面都是承受流量冲击的大头,需隔离开(非功能性需求)。同时因秒杀活动特性,商品属极端供不应求的场景,卖家占优势,所以可做服务降级,以降低计算资源消耗、提高性能(定制化逻辑)。如:

  • 商详页可将履约时效拿掉,不再计算预计多久能到货。还可拿掉评价信息,不再展示评价
  • 下单页可不再计算优惠金额分摊,秒杀商品不参与任何叠加优惠活动。仅保留必要信息,如商品信息,商品主图,购买按钮,下单按钮等
  • 结算页、收银台,则看情况,若流量压力不大,可不用物理隔离:
    • 支付扣减库存下单的压力会直接传递到结算
    • 但下单扣减就不需要并发支付,仅抢到的用户需结算,压力就很小
    • 为降低流量影响面积,这里假设下单扣减,毕竟秒杀商品也不怕客户下单后不支付

秒杀商品不怕客户不支付的原因

  • 商品吸引力:秒杀商品往往是极具吸引力的折扣商品,抢购用户通常都会完成支付,未支付的比例较低
  • 多次释放机制:即使有用户不支付,库存会在短时间内释放出来,其他用户可以继续抢购,这个过程在秒杀活动的激烈程度下通常很快完成。

最后,商品购买成功还需要依赖,订单系统创建订单,库存系统扣减商品库存,结算系统确认支付等等步骤。到达这里,流量相对已较平稳,且逻辑上没啥定制化诉求(压力小,没必要围绕性能做定制化),所以采用逻辑隔离复用原交易系统的集群。逻辑隔离两种实现思路:

  • 依赖限流框架,如在订单系统设置来源是秒杀系统BFF的创建订单请求,TPS不超100,并发连接数不能超过20
  • 依赖RPC框架,RPC框架可设置分组,只把订单系统集群里面部分服务节点设置成“秒杀组”,再把秒杀服务BFF的客户端也设置为“秒杀组”,那么秒杀系统的流量就只会打到订单系统集群里面属于“秒杀组”的节点上。这种隔离方式分割了集群,集群节点少了,出现故障发生过载的可能就提高了,可能会导致秒杀系统不可用

Q:为啥集群节点少了,出现故障发生过载的可能就提高?

A:好比公里原本4条道能并行4辆车,现在给按车辆类型分成了机动车和公交车专用,机动车道2条。如果其中1条机动车道发生车祸,原本分散在2条道上的车流就要汇聚在1条道,原本顺畅的通行可能立马就开始堵车了。

1.2 多级缓存

在系统的多个层级进行数据缓存,以提高响应效率,高并发架构中最常用方案之一。

1.2.1 DNS层

一般将静态资源挂到CDN上,借助CDN来分流和提高响应效率。以秒杀系统为例,就是将秒杀前端系统的商详页和下单页缓存到CDN网络上。

借助CDN的用户请求链路:

如果用户终端有页面缓存就走终端本地缓存,没有就请求远端CDN的域名(静态资源走CDN域名),请求来到DNS调度的节点,调度一个最近的CDN节点,如果该CDN节点有页面缓存则返回,没有则向缘站发起溯源,请求就会走普通链路过秒杀系统ng到秒杀系统前端。

1.2.2 网关层

网关这个有多种组合情况,最简单的就是一个接入层网关加一个应用层网关,比如:ISV(四层)-> Nginx(七层)。以这个为例,这里的缓存优化主要看接入层的负载均衡算法和应用层的本地缓存和集中内存缓存。

缓存还要提LB算法,是因为节点的本地缓存的有效性和LB算法强绑定。常用LB算法有轮询(也叫取模)和一致性哈希:

  • 轮询可以让请求分发更均衡,但同个缓存key的请求不一定会路由到同个应用层Nginx上,Nginx的本地缓存命中率低
  • 一致性哈希可让同个缓存key路由到同个应用层Nginx上,Nginx的本地缓存命中率高,但其请求分发不均衡容易出现单机热点问题。有种做法是设置一个阈值,当单节点请求超过阈值时改为轮询,可以算是自适应性负载均衡的变种。但这种基于阈值判断的做法在应对真正的高并发时效果并不理想。

所以想运用本地缓存强依赖业务运营,需对每个热点商品key有较为准确的流量预估,并人为的组合这些商品key,进而控制流量均匀的落到每个应用层Nginx上(其实就是数据分片,然后每片数据流量一致)。这非常困难,所以笔者认为,还是采用轮询加集中内存缓存比较简单有效。

从接入层开始带有本地缓存和集中内存缓存的请求链路:

1.2.3 服务层
应用层ngnix->秒杀系统BFF->订单服务

其实两两组合和网关层是一样的场景。应用层ngnix基于ngnix的负载均衡转发请求到秒杀系统BFF,秒杀系统BFF基于RPC框架的负载均衡转发请求到订单服务。都面临着负载均衡策略选择和是否启用本地缓存的问题。不一样的点只是缓存的粒度和启用缓存的技术栈选择。

1.2.4 多级缓存失效

因为缓存分散到多层,很难用单一技术栈应对缓存失效问题,但都等到缓存过期,这种更新时延较长又不一定能被业务接受。

有个做法是基于DB的binlog监听,各层监听自己相关的binlog信息,在发生缓存被变更的情况时,及时让集成内存的缓存失效。

本地缓存在这里还有个缺陷,就是缓存失效时需要广播到所有节点,让每个节点都失效,对于频繁变更的热key就可能产生消息风暴。

1.3 无损消峰

为流量峰值准备对应的服务集群,首先成本太高,接着单纯的水平扩展也不一定能做到(分布式架构存在量变引起质变的问题,资源扩展到一定量级,原先的技术方案整个就不适用了。

如当集群节点太多,服务注册发现可能会有消息风暴;出入口的带宽出现瓶颈,需要在部署上分流)。更别说这个峰值也不受控制,想要高枕无忧就会有很高的冗余浪费。

所以一般采用消峰:

  • 直接断头,把超出负荷的流量直接都丢弃掉,也就是我们常见的限流,也称为有损消峰(如果这是大促的订单,砍掉的可能都是钱,这个有损是真的资损)
  • 分流,也叫消峰填谷,通过技术或者业务手段将请求错开,铺到更长的时间线上,从而降低峰值,常见的有MQ异步消费和验证码问答题。先谈无损消峰
1.3.1 MQ异步消费

MQ依赖三个特性可以做到平滑的最终一致,分别是:

  • 有消息堆积才能起到蓄水池的效果,在出水口流速恒定的情况下能接住入水口瞬时的大流量
  • 有匀速消费才能让下游集群的流量压力恒定,不会被冲击
  • 有至少成功一次,才能保证事物最终一致

以秒杀系统BFF下单操作向订单服务创建订单为例。如果没有消息队列(MQ),同时有100W个创建请求,订单系统就必须承担100W个并行连接的压力。但是,如果使用了MQ,那么100W个创建请求的压力将全部转移到MQ服务端,订单系统只需要维持64个并行连接,以稳定地消费MQ服务端的消息。

这样一来,订单系统的集群规模就可以大大减小,而且更重要的是,系统的稳定性得到了保障。由于并行连接数的减少,资源竞争也会降低,整体响应效率也会提高,就像在食堂排队打饭一样,有序排队比乱抢效率更高。但是,用户体验可能会受到影响,因为点击抢购后可能会收到排队提示(其实就是友好提示),需要延迟几十秒甚至几分钟才能收到抢购结果。

1.3.2 验证码问答题

两层好处:

  • 消峰,用户0.5秒内并发的下单事件,因为个人的手速差异,被平滑的分散到几秒甚至几十秒中
  • 防刷,提高机器作弊成本
验证码

基本实现步骤:

  • 请求到来时生成1串6位随机字符串 verification_code

  • 用特定前缀拼接用户ID作为key,verification_code做为value存redis,超时5s

  • 生成一个图片,将 verification_code 写到图片上,返回给用户

  • 用户输入图片中字符串

  • 从redis里面取出 verification_code 做比对,如果一致,执行下单操作

但这样其实是可以用暴力破解的,比如,用机器仿照一个用户发起10W个请求携带不同的6位随机字符。所以校验验证码时可以使用 GETDEL ,让验证码校验无论对错都让验证码失效。

问答题

基本实现思路和验证码几乎一样。差别在于,问答题的题库要提前生成,请求到来时从题库中拿到一组问题和答案。然后把答案存redis,问题塞到图片里返回给用户。

验证码和问答题具有很好的消峰效果。特别是问答题,想要提高消峰效果只要提高问题难度就行,例如,笔者曾经在12306上连续错了十几次问答题。但是这也是用户体验有损的,例如,虽然笔者当初未能成功抢到票而感到沮丧,但这魔性的题库依然把笔者成功逗笑。

无损消峰,无损了流量,但损失了用户体验。现如今技术水平在不断进步,解决方法在增多,这些有损用户体验的技术方案可能都会慢慢退出历史舞台,就像淘宝取消618预售。 关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化

  • 活动&券等营销中台建设

  • 交易平台及数据中台等架构和开发设计

  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化

  • LLM Agent应用开发

  • 区块链应用开发

  • 大数据开发挖掘经验

  • 推荐系统项目

    目前主攻市级软件项目设计、构建服务全社会的应用系统。 本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

Long Short-Term Memory

这篇论文总结的太抽象了,只是翻译了一遍。 (我太笨了,如果把这个当我的入门读物,我觉着会把我折磨坏) 递归神经网络的一个重要优点是它们在映射输入和输出序列时使用上下文信息的能力。不幸的是,对于标准的…

51单片机——按键控制

1、按键介绍 轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。 2、按键的抖动 对于机械开关,当机械触点断开、闭合时,由于…

基于SpringBoot+Vue的家教管理系统

文章目录 前言1.项目类型2.技术栈介绍1.客户端技术栈介绍2.服务端技术栈介绍 3.功能介绍1.客户端功能2.服务单功能 4.项目亮点5.适用场景6.项目展示1.客户端展示2.服务端展示 7.诚邀参与 前言 大家好,我是执手天涯,今天非常荣幸地向大家介绍一款基于Spr…

关于ssrf的实现

ssrf漏洞形成 SSRF(Server-Side Request Forgery:服务器端请求伪造)漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤 ssrf实现 本次ssrf于Pikachu靶场上实现 我们可以先拉取镜像 docker …

计算机毕业设计Spark+Tensorflow股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

1. 需求分析 基于Spark的股票大数据分析及可视化系统是一个利用Spark分布式计算框架进行股票市场数据处理、分析和可视化的系统。它能够处理大规模的实时股票数据,包括股票价格、交易量、市场指标等,提供实时数据处理、数据可视化与展示和并提供相应决策…

【图像增强】使用 Albumentations Python 库(02)

一、说明 在本博客的第 1 部分中,我介绍了使用 Albumentations Python 库进行图像增广的基础知识。本部分介绍高级详细信息。 二、使用 Albumentations 进行语义分割任务 我们将使用来自 TGS 盐鉴定挑战赛的图像和数据。TGS Salt Identification Challenge | Kaggl…

基于carsim的线控转向仿真(2)--齿条力观测

观测器更详细的介绍文章可以关注博主以下两篇文章 从小车倒立摆系统看系统建模控制LQRLQE仿真_lqr平衡小车仿真模型-CSDN博客 好玩的直流电机调速实验、PID、极点配置、LQR、观测器;不讲大道理_观测器极点配置-CSDN博客 三个实例迅速掌握经典卡尔曼滤波用法_卡尔…

VIM的简单用法

vim三种模式的切换 Set nu:显示行号 Set nonu:不显示行号 Set mousea显示鼠标光标 Set cursorline:显示行线 为什么这些设定默认不能永久存在: 进程结束后,所占的内存空间会被系统回收,资源被释放,这些资源…

国内号码验证注册谷歌邮箱【亲测有效】

前言: 谷歌邮箱可以无需注册直接登录很多软件,但是直接很多人直接注册都会表示国内号码注册不了,所以需求还是有的,这里我尝试一下,顺便记录一下​。 ​环境前提:魔法 ​正文: 打开魔法,开启…

react笔记(React18)

以下笔记可能毫无章法,仅供个人学习记录使用。 关于状态提升: 状态提升适用于兄弟组件之间传递数据,共享状态,其实就是把两个兄弟组件要共同使用的数据存放到共同的父组件中,称状态提升。 关于context跨层级组件通信…

5步掌握“花开富贵”花园管理系统开发——基于Python Django+Vue

🍊作者:计算机毕设匠心工作室 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目…

Java超市收银系统(十、爬虫)

引言 爬虫功能实现,要求爬取页面数据至少100条,这里以豆瓣音乐为示例编写代码豆瓣音乐标签: 民谣 (douban.com)。 功能实现 除了爬虫功能增加,代码其他内容原理和之前博客发布是一致的,只不过这里为了区分,我们重新创…

IDM是海外加速器吗 IDM在国内好用吗

IDM是一款出色的下载加速器,它可以将下载任务分割成多个部分,利用多线程技术加速下载速度,支持断点续传功能,能够从上次下载中断的地方继续下载,提高了下载效率和稳定性,所以深受年轻人的欢迎。 一、IDM是…

集合及数据结构第十节(下)————常用接口介绍、堆的应用和java对象的比较

系列文章目录 集合及数据结构第十节(下)————常用接口介绍和堆的应用 常用接口介绍和堆的应用 PriorityQueue的特性.PriorityQueue常用接口介绍top-k问题堆排序PriorityQueue中插入对象元素的比较.对象的比较.集合框架中PriorityQueue的比较方式 文…

《系统架构设计师教程(第2版)》第15章-面向服务架构设计理论与实践-04-SOA设计

文章目录 1. SOA设计的标准要求1.1 文档标准1.2 通信协议标准1.3 应用程序统一登记与集成1.4 服务质量 (QoS)1.4.1 可靠性1.4.2 安全性1.4.3 策略1.4.4 控制1.4.5 管理 2. SOA的设计原则 1. SOA设计的标准要求 OASIS Organization for the Advancement of Structured Informati…

RISCV汇编编程讲解

第一章 引言 为什么要讲riscv? riscv的特点: -诞生于顶尖学术机构:诞生于加州大学伯克利分校的体系结构研究院。吸引了大批的顶尖企业参与(e.g. 谷歌、华为、高通、阿里巴巴为rsicv的发展提供了大量的资金支持和贡献了技术和人才…

【计算机网络】名词解释--网络专有名词详解(更新)

在网络通信中,有许多专业术语和概念,它们共同构成了网络通信的基础。以下是一些常见的网络术语及其定义和相互之间的关系: 一、网络基础 1.1 电路交换:电路交换是一种在数据传输前建立专用通信路径的通信方式。在通信开始前&…

RAG 技术原理

目录 RAG 技术原理背景和概念实现步骤1. ChatGPT/GLM 等大语言模型的调用2. 读取知识库数据3. 文本索引与答案检索4. 文本嵌入与向量检索5. 文本多路召回与重排序6. 文本问答Promopt优化 原创链接 RAG 技术原理 背景和概念 在自然语言处理领域,大型语言模型&#x…

使用 C 语言实现字符走迷宫 DFS算法应用

使用 C 语言实现字符走迷宫 DFS算法应用 迷宫问题是一个经典的编程问题,通常用于算法训练。我们将通过使用 C 语言来实现一个字符迷宫的求解,其中玩家可以控制字符在迷宫中移动,直到找到出口。 1. 问题描述 我们将设计一个二维迷宫&#xf…

Unity--AnimationCurve动画曲线设置

参考文章:https://blog.csdn.net/qq_20179331/article/details/131309128 打开Clip文件点击Curves选项,选中想要编辑的动作关键帧,右键选择Auto 这样动画就变成线性的了