大秒杀系统设计

参考链接:http://www.taodudu.cc/news/show-5770725.html?action=onClick

1. 一些数据

大家还记得2013年的小米秒杀吗?三款小米手机各11万台开卖,走的都是大秒系统,3分钟后成为双十一第一家也是最快破亿的旗舰店。
经过日志统计,前端系统双11峰值有效请求约60w以上的QPS ,而后端cache的集群峰值近2000w/s、单机也近30w/s,但到真正的写时流量要小很多了,当时最高下单减库存tps是红米创造,达到1500/s。

2. 热点隔离

秒杀系统设计的第一个原则就是将这种热点数据隔离出来,不要让1%的请求影响到另外的99%,隔离出来后也更方便对这1%的请求做针对性优化。针对秒杀我们做了多个层次的隔离:

  • 业务隔离。把秒杀做成一种营销活动,卖家要参加秒杀这种营销活动需要单独报名,从技术上来说,卖家报名后对我们来说就是已知热点,当真正开始时我们可以提前做好预热。
  • 系统隔离。系统隔离更多是运行时的隔离,可以通过分组部署的方式和另外99%分开。秒杀还申请了单独的域名,目的也是让请求落到不同的集群中。
  • 数据隔离。秒杀所调用的数据大部分都是热数据,比如会启用单独cache集群或MySQL数据库来放热点数据,目前也是不想0.01%的数据影响另外99.99%。

当然实现隔离很有多办法,如:
可以按照用户来区分,给不同用户分配不同cookie,在接入层路由到不同服务接口中;还有在接入层可以对URL的不同Path来设置限流策略等。
服务层通过调用不同的服务接口;
数据层可以给数据打上特殊的标来区分。
目的都是把已经识别出来的热点和普通请求区分开来。

3. 动静分离

前面介绍在系统层面上的原则是要做隔离,接下去就是要把热点数据进行动静分离,这也是解决大流量系统的一个重要原则。我们的大秒系统是从商品详情系统发展而来,所以本身已经实现了动静分离,如下图所示
在这里插入图片描述
大秒系统动静分离
除此之外还有如下特点:

  1. 把整个页面Cache在用户浏览器
  2. 如果强制刷新整个页面,也会请求到CDN
  3. 实际有效请求只是“刷新抢宝”按钮

这样把90%的静态数据缓存在用户端或者CDN上,当真正秒杀时用户只需要点击特殊的按钮“刷新抢宝”即可,而不需要刷新整个页面,这样只向服务端请求很少的有效数据,而不需要重复请求大量静态数据。
秒杀的动态数据和普通的详情页面的动态数据相比更少,性能也比普通的详情提升3倍以上。所以“刷新抢宝”这种设计思路很好地解决了不刷新页面就能请求到服务端最新的动态数据。

4. 基于时间分片削峰

熟悉淘宝秒杀的都知道,第一版的秒杀系统本身并没有答题功能,后面才增加了秒杀答题,当然秒杀答题一个很重要的目的是为了防止秒杀器,2011年秒杀非常火的时候,秒杀器也比较猖獗,而没有达到全民参与和营销的目的,所以增加的答题来限制秒杀器。增加答题后,下单的时间基本控制在2s后,秒杀器的下单比例也下降到5%以下。新的答题页面如下图所示。
在这里插入图片描述
秒答题页面

其实增加答题还有一个重要的功能,就是把峰值的下单请求给拉长了,从以前的1s之内延长到2~10s左右,请求峰值基于时间分片了,这个时间的分片对服务端处理并发非常重要,会减轻很大压力,另外由于请求的先后,靠后的请求自然也没有库存了,也根本到不了最后的下单步骤,所以真正的并发写就非常有限了。其实这种设计思路目前也非常普遍,如支付宝的“咻一咻”已及微信的摇一摇。

除了在前端通过答题在用户端进行流量削峰外,在服务端一般通过锁或者队列来控制瞬间请求。

5. 数据分层校验

在这里插入图片描述
分层校验
对大流量系统的数据做分层校验也是最重要的设计原则,所谓分层校验就是对大量的请求做成“漏斗”式设计,如图3所示:在不同层次尽可能把无效的请求过滤,“漏斗”的最末端才是有效的请求,要达到这个效果必须对数据做分层的校验,下面是一些原则:

先做数据的动静分离
将90%的数据缓存在客户端浏览器
将动态请求的读数据Cache在Web端
对读数据不做强一致性校验
对写数据进行基于时间的合理分片
对写请求做限流保护
对写数据进行强一致性校验

秒杀系统正是按照这个原则设计的系统架构,如下图所示。
在这里插入图片描述
秒杀系统分层架构

6. 实时热点发现

其实秒杀系统本质是还是一个数据读的热点问题,而且是最简单一种,因为在文提到通过业务隔离,我们已能提前识别出这些热点数据,我们可以提前做一些保护,提前识别的热点数据处理起来还相对简单,比如分析历史成交记录发现哪些商品比较热门,分析用户的购物车记录也可以发现那些商品可能会比较好卖,这些都是可以提前分析出来的热点。比较困难的是那种我们提前发现不了突然成为热点的商品成为热点,这种就要通过实时热点数据分析了,目前我们设计可以在3s内发现交易链路上的实时热点数据,然后根据实时发现的热点数据每个系统做实时保护。 具体实现如下:

  1. 构建一个异步的可以收集交易链路上各个中间件产品如Tengine、Tair缓存、HSF等本身的统计的热点key(Tengine和Tair缓存等中间件产品本身已经有热点统计模块)。
  2. 建立一个热点上报和可以按照需求订阅的热点服务的下发规范,主要目的是通过交易链路上各个系统(详情、购物车、交易、优惠、库存、物流)访问的时间差,把上游已经发现的热点能够透传给下游系统,提前做好保护。比如大促高峰期详情系统是最早知道的,在统计接入层上Tengine模块统计的热点URL。
  3. 将上游的系统收集到热点数据发送到热点服务台上,然后下游系统如交易系统就会知道哪些商品被频繁调用,然后做热点保护。如下图所示。

在这里插入图片描述
实时热点数据后台
重要的几个:其中关键部分包括:

  • 这个热点服务后台抓取热点数据日志最好是异步的,一方面便于做到通用性,另一方面不影响业务系统和中间件产品的主流程。
  • 热点服务后台、现有各个中间件和应用在做的没有取代关系,每个中间件和应用还需要保护自己,热点服务后台提供一个收集热点数据提供热点订阅服务的统一规范和工具,便于把各个系统热点数据透明出来。
  • 热点发现要做到实时(3s内)。

7. 关键技术优化点

前面介绍了一些如何设计大流量读系统中用到的原则,但是当这些手段都用了,还是有大流量涌入该如何处理呢?秒杀系统要解决几个关键问题。

7.1 Java处理大并发动态请求优化

???

7.2 同一商品大并发读问题

你会说这个问题很容易解决,无非放到Tair缓存里面就行,集中式Tair缓存为了保证命中率,一般都会采用一致性Hash,所以同一个key会落到一台机器上,虽然我们的Tair缓存机器单台也能支撑30w/s的请求,但是像大秒这种级别的热点商品还远不够,那如何彻底解决这种单点瓶颈?答案是采用应用层的Localcache,即在秒杀系统的单机上缓存商品相关的数据,如何cache数据?也分动态和静态:

  • 像商品中的标题和描述这些本身不变的会在秒杀开始之前全量推送到秒杀机器上并一直缓存直到秒杀结束。
  • 像库存这种动态数据会采用被动失效的方式缓存一定时间(一般是数秒),失效后再去Tair缓存拉取最新的数据。

你可能会有疑问,像库存这种频繁更新数据一旦数据不一致会不会导致超卖?其实这就要用到我们前面介绍的读数据分层校验原则了,读的场景可以允许一定的脏数据,因为这里的误判只会导致少量一些原本已经没有库存的下单请求误认为还有库存而已,等到真正写数据时再保证最终的一致性。这样在数据的高可用性和一致性做平衡来解决这种高并发的数据读取问题。

7.3 同一数据大并发更新问题

解决大并发读问题采用Localcache和数据的分层校验的方式,但是无论如何像减库存这种大并发写还是避免不了,这也是秒杀这个场景下最核心的技术难题。

同一数据在数据库里肯定是一行存储(MySQL),所以会有大量的线程来竞争InnoDB行锁,当并发度越高时等待的线程也会越多,TPS会下降RT会上升,数据库的吞吐量会严重受到影响。说到这里会出现一个问题,就是单个热点商品会影响整个数据库的性能,就会出现我们不愿意看到的0.01%商品影响99.99%的商品,所以一个思路也是要遵循前面介绍第一个原则进行隔离,把热点商品放到单独的热点库中。但是无疑也会带来维护的麻烦(要做热点数据的动态迁移以及单独的数据库等)。

分离热点商品到单独的数据库还是没有解决并发锁的问题,要解决并发锁有两层办法。

  • 应用层做排队。按照商品维度设置队列顺序执行,这样能减少同一台机器对数据库同一行记录操作的并发度,同时也能控制单个商品占用数据库连接的数量,防止热点商品占用太多数据库连接。
  • 数据库层做排队。应用层只能做到单机排队,但应用机器数本身很多,这种排队方式控制并发仍然有限,所以如果能在数据库层做全局排队是最理想的,淘宝的数据库团队开发了针对这种MySQL的InnoDB层上的patch,可以做到数据库层上对单行记录做到并发排队,如下图所示。

在这里插入图片描述
数据库层对单行记录并发排队

你可能会问排队和锁竞争不要等待吗?有啥区别?如果熟悉MySQL会知道,InnoDB内部的死锁检测以及MySQL Server和InnoDB的切换会比较耗性能,淘宝的MySQL核心团队还做了很多其他方面的优化,如COMMIT_ON_SUCCESS和ROLLBACK_ON_FAIL的patch,配合在SQL里面加hint,在事务里不需要等待应用层提交COMMIT而在数据执行完最后一条SQL后直接根据TARGET_AFFECT_ROW结果提交或回滚,可以减少网络的等待时间(平均约0.7ms)。据我所知,目前阿里MySQL团队已将这些patch及提交给MySQL官方评审。

8. 大促热点问题思考

以秒杀这个典型系统为代表的热点问题根据多年经验我总结了些通用原则:隔离、动态分离、分层校验,必须从整个全链路来考虑和优化每个环节,除了优化系统提升性能,做好限流和保护也是必备的功课

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

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

相关文章

appium+jenkins实例构建

自动化测试平台 Jenkins简介 是一个开源软件项目,是基于java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。 前面我们已经开完测试脚本,也使用bat 批处…

文件上传之图片码混淆绕过(upload的16,17关)

目录 1.upload16关 1.上传gif loadup17关(文件内容检查,图片二次渲染) 1.上传gif(同上面步骤相同) 2.条件竞争 1.upload16关 1.上传gif imagecreatefromxxxx函数把图片内容打散,,但是不会…

MySQL用户管理

文章目录 MySQL用户管理1. 用户1.1 用户信息1.2 创建用户1.3 删除用户1.4 修改用户密码 2. 数据库的权限2.1 给用户授权2.2 回收权限2.2 回收权限 MySQL用户管理 如果我们只能使用root用户,这样存在安全隐患。这时,就需要使用MySQL的用户管理。 1. 用户…

flink的几种常见的执行模式

背景 在运行flink时,我们经常会有几种不同的执行模式,比如在IDE中启动时,通过提交到YARN上,还有通过Kebernates启动时,本文就来记录一下这几种模式 flink的几种执行模式 flink嵌入式模式: 这是一种我们在…

自考本科,毕业八年,2023浙大MPA提面优秀分享

去年十月中旬,我参加了浙江大学MPA提前批面试。结果出乎意料地,我竟然获得了A资格。对此,我自己也感到难以置信。事实上,我只是抱着试一试的心态递交了申请材料。因为通过我对前几年浙大自划线的情况来看,对于浙江大学…

用postman 推送消息到GCP的pubsub

创建1个Topic 和 2个 subscription 我们可以用terraform 去创建1个topic 和 2个subscriptions # topic resource "google_pubsub_topic" "topic_a" {name "TopicA"project var.project_id }# subscriptions resource "google_pubsub_s…

SpringMVC的常用注解,参数传递以及页面跳转的使用

目录 slf4j 常用注解 RequestMapping RequestParam RequestBody PathVariable 参数传递 首先在pom.xml配置文件中导入SLF4J的依赖 基础类型String 复杂类型 RequestParam PathVariable RequestBody 增删改查 返回值 void返回值 String返回值 modelString …

【算法】分治法的应用——快速排序

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ …

关于黑马hive课程案例FineBI中文乱码的解决

文章目录 问题描述情况一的解决情况二的解决 ETL数据清洗知识社交案例参考代码结果展示 问题描述 情况1&#xff1a;FineBI导入表名中文乱码&#xff0c;字段内容正常情况2&#xff1a;FineBI导入表字段中文乱码&#xff0c;表名内容正常 情况一的解决 使用navcat等工具连接…

Docker如何安装seafile

SQLite 方式 要在 Docker 中安装 Seafile&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装 Docker&#xff1a;确保您的系统上已经安装了 Docker。您可以根据您的操作系统类型&#xff0c;在官方网站上找到适合您系统的 Docker 版本并进行安装。 下载 Seafile 镜像&…

第16章_瑞萨MCU零基础入门系列教程之CAN 协议

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

Linux CentOS7命令及命令行

Linux CentOS7中命令及命令行是非常重要的概念。对大多数初学者来说是既熟悉又了解甚少。本文初步讨论这方面的内容&#xff0c;与同行者交流。 一、命令 命令又称为指令&#xff0c;&#xff08;英语命令 command&#xff0c;可用简写cmd表示&#xff09;&#xff0c;在终端…

Spring Boot集成JasperReport生成文档

由于工作需要&#xff0c;要实现后端根据模板动态填充数据生成PDF文档&#xff0c;通过技术选型&#xff0c;使用Ireport5.6来设计模板&#xff0c;结合JasperReports5.6工具库来调用渲染生成PDF文档。 一、使用Ireport designer 5.6设计模板 ireport的使用由于时间关系不便多…

ISYSTEM调试实践12-软件运行时间的优化

实际工程的运行要比上篇文章提到的例程复杂的多 ISYSTEM调试实践11-Profiler Timeline和软件运行时间分析 由于复杂的应用层模型和底层任务&#xff0c;假定应用层模型的运行周期是10ms&#xff0c;任务函数的执行时间往往超过1ms&#xff0c;这时候就必须要考虑函数执行本身的…

sqli --【1--10】

Less-1&#xff08;联合查询&#xff09; 1.查看是否有回显 2.查看是否有报错 3.使用联合查询&#xff08;字符注入&#xff09; 3.1判断其列数 3.2 判断显示位置 3.3敏感信息查询 Less-2&#xff08;联合查询&#xff09; 1.查看是否有回显 2.查看是否有报错 3.使用…

idea启动缓慢解决办法

idea启动缓慢解决办法 文章目录 idea启动缓慢解决办法前言一、修改内存大小二、虚拟机运行大小三、插件禁用1、安卓相关2、构建工具3、Code Coverage 代码覆盖率4、数据库5、部署工具6、html和xml7、ide settings8、JavaScript框架和工具9、jvm框架10、Keymap快捷键映射11、kot…

Java中快速排序的优化技巧:随机取样、三数取中和插入排序

目录 快速排序基础 优化1&#xff1a;随机取样 优化2&#xff1a;三数取中 优化3&#xff1a;插入排序 总结&#xff1a; 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;它的平均时间复杂度为O(n log n)。然而&#xff0c;在某些情况下&…

基于视觉重定位的室内AR导航项目思路(2):改进的建图和定位分离的项目思路

文章目录 一、建图二、定位首先是第一种方法&#xff1a;几何方法其次是第二种方法&#xff1a;图像检索方法最后是第三种方法&#xff1a;深度学习方法 前情提要&#xff1a; 是第一次做项目的小白&#xff0c;文章内的资料介绍如有错误&#xff0c;请多包含&#xff01; 一、…

从 LinkedHashMap 源码到手撕 LRU 缓存

大家好&#xff0c;我是 方圆。最近在刷 LeetCode 上LRU缓存的题目&#xff0c;发现答案中有 LinkedHashMap 和自己定义双向链表的两种解法&#xff0c;但是我对 LinkedHashMap 相关源码并不清楚&#xff0c;所以准备学习和记录一下。如果大家想要找刷题路线的话&#xff0c;可…

Redis:实现全局唯一id

&#xff08;笔记总结自《黑马点评》项目&#xff09; 一、全局ID生成器 全局ID生成器&#xff0c;是一种在分布式系统下用来生成全局唯一ID的工具&#xff0c;一般要满足下列特性&#xff1a; 二、原理 为了增加ID的安全性&#xff0c;我们可以不直接使用Redis自增的数值&…