资讯详情

如何设计一个秒杀系统?

两个核心问题:

并发读 并发写

秒杀整体结构:稳定快速 稳定性:系统架构可用性高,确保活动顺利完成 准:不超卖 快:rt低,整体链路协调优化

<–深化一下–>

高性能: 如何支持高并发写涉及大量秒杀的并发读写? 1.设计数据动静分离 2.发现和隔离热点 3.要求的峰值和分层过滤 4.终极优化服务端

一致性: 核心:如何设计秒杀库存方案

高可用: planB兜底

设计秒杀系统的五个架构原则:4.1 1.尽量少数据 1.1 用户请求数据可以少,请求数据包括上传到系统数据和系统返回到用户数据(网页数据),因为数据需要时间在网络上传输,然后请求数据或返回数据需要服务器处理,如序列、压缩、字符编码等,这些处理非常消耗cpu因此,可以显著减少传输的数据量cpu的使用。比如简化秒杀页面大小,去掉不必要的页面装饰效果等等。 1.2 依赖的数据越少越好。许多客户/前端学生希望调用尽可能少的接口以获取更多信息。没有按需要求。例如,页面只显示歌曲信息,但除了歌曲信息外,接口还返回标签、风格等不必要的信息。调用其他服务将涉及序列化和反序列化,这也是cpu一个大杀手,同时整个请求rt也会上升,rt慢了,机器负载load也会上升,引起连反应。

2.尽量少要求 在用户要求的页面返回后,浏览器渲染依赖于多个页面css/javascript/图片和其他文件。与页面所需的核心数据相比,这些请求被定义为额外请求(无需每次重新下载和定值)css文件和JavaScript多个文件 JavaScript 文件合并成文件,在 URL 用逗号隔开(https://g.xxx.com/tm/xx-b/4.0.94/mods/???module-preview/index.xtpl.js,module-jhs/index.xtpl.js,module-focus/index.xtpl.js)。这样,单个文件仍然存储在服务端,但服务端将有一个组件分析 URL,然后动态合并这些文件并返回。

3.路径应尽可能短 将多个相互依赖的应用依赖的应用,远程部署RPC调用变成JVM如果节点服务的可用性是99.9%,如果一个请求通过五个节点,整个请求的可用性将变为99.9%的5次方,约等于99.5%。

4.尽量少依赖 简单来说,我们应该根据重要性对系统依赖的服务进行分类,比如getSongs获取歌曲信息接口,歌曲服务为0级,艺术家/专辑信息数据1级,标签/歌曲风格流派等服务为2级。在促销期间,非0级服务可以降级,以确保核心服务的稳定性。

5.分布式,没有单点 单点意味着没有备份,风险无法控制。任何服务都应分布式,以避免与机器绑定服务状态。

秒杀系统演绎过程

1W QPS 商品购买页 -> 服务端 -> 增删改查数据库

10W QPS 核心:秒杀系统升级 独立集群在系统部署中,抵御流量洪峰 将库存数据放入缓存中,以提高读取性能 增加秒杀答案,防止秒杀器抢单 在这里插入图片描述

100W QPS 动态和静态分离页面,尽量减少页面刷新量和动态资源请求。 服务端本地缓存秒杀货物,无需调用依赖系统的后台服务获取数据,甚至无需到公共缓存集群查询数据,进一步降低服务端压力 增加系统限流保护 通过策略降低系统压力

如何做好动静分离?有哪些选择? 如何区分动态数据和静态数据? 主要区别在于页面中输出的数据是否与URL、浏览器、时间、地域相关,是否包含Cookie等私密数据,即页面展示的数据中是否包含个性化的数据。举两个例子: 1.新闻网站,千人一面,用户、时间、地域等信息的变化不会影响页面的显示,这类数据数据静态页面。 2.手淘首页,千人千面,基本都是个性化数据,属于动态页面。

如何缓存静态数据? 1.静态改造,简而言之是直接缓存http连接,如静态数据存储CDN,将内容放置在最接近用户的服务器中,以减少骨干网络和城市网络之间的网络延迟。 2.选择缓存静态数据的合适方式,用不同的语言书写Cache缓存处理效率不同,java系统本身不适合处理大量的连接请求,每个连接消耗更多的内存,servlet容器解析http协议慢,可以不在java缓存在系统层,Web在服务器上做,屏蔽java语言层面的一些弱点,可以在nginx,apache层进行全局控制,Web服务器也更擅长处理大并发的静态文件请求。

动静分离的几种架构方案? 静态数据和动态数据通过改造分离,那么如何在系统架构上进一步组合这些动态和静态数据,然后完全输出给用户呢? 可选三种方案: 1.实体机单机部署 2.统一cache层 3.上cdn 此外,还可以: 1.用户浏览器中缓存了整个页面 2.实际有效要求减少,但用户点击刷新抢宝按钮

静态资源走cdn缓存 动态内容服务端cache

第三章 有针对性地处理系统的热点数据

什么是热点? 热点分为热点操作和热点数据 热点操作: 如购物车、商品细节、交易订单等 热点数据: 如热门商品等

如何处理热点数据? 处理热点数据通常有几个想法:一是优化,二是限制,三是隔离。 优化: 1.缓存lru 2.例如,对于被访问的商品 ID 做一致性 Hash,然后根据 Hash 制作分桶,每个分桶设置一个处理队列,将热点商品限制在请求队列中,防止其他请求因某些热点商品占用过多的服务器资源而无法获得服务器处理资源。(Q:分桶?怎么做? 3.隔离 业务隔离。把秒杀变成营销活动,卖家需要单独注册才能参与秒杀。从技术上讲,卖家注册后有一个已知的热点,所以我们可以提前预热。 系统隔离。系统隔离更多的是运行中的隔离,可以分组部署和其他 99% 分开。秒杀可以申请单独的域名,目的是让请求落入不同的集群。 数据隔离。秒杀调用的数据大多是热点数据,比如单独使用 Cache 集群或者 MySQL 数据库放热点数据的目的是不想 0.01% 影响数据的机会 99.99% 数据。

第四章 如何做好流量削峰

思路: 无损:排队、回答、分层过滤 损坏:限流、机器负载保护等强制措施

排队(简单来说就是一步变多步): 消息队列缓冲瞬时流量 加锁等待线程池 先进先出。先进后出等内存排队算法 请求序列化文件,再顺序读取文件,类似mysql binlog

答题: 功效:防止刷量作弊 延缓请求

分层过滤:尽量减少无用要求,如减少不必要的一致性验证等

第五章 影响性能的因素有哪些?如何提高系统的性能?

一般有两个因素:一次响应的服务端耗时和线程数 响应时间一般是由cpu由执行时间和线程等待时间组成,通过测试发现线程等待时间不有用,因为这可以通过增加线程数量来弥补,主要是cpu由于执行时间能有真正的影响,因为cpu如果服务器资源被减少,执行将真正消耗cpu一半的执行时间,就可以增加一倍的qps

需要注意的是,不同的系统对瓶颈有不同的关注。例如,对于缓存系统,内存受到限制,存储系统受到限制I/O瓶颈更容易。 对于秒杀系统来说,瓶颈更多地发生在CPU上

如何优化系统 1.减少编码 java编码运行缓慢,是的java在很多情况下,只要涉及到字符串的操作(如输入输出操作),I/O操作)都比较浩cpu无论是磁盘,资源i/o还是网络i/o,因为字符需要转换为字节,这个过程必须转换。 同时,每个字符的编码都需要检查表,这种检查表的操作消耗了大量的资源,因此有效地减少了字符和字节之间的转换。 如何减少编码?提前将数据转换为字节,减少静态数据编码转换

2.减少序列化 序列化也是Java由于序列化和编码往往同时发生,因此性能的天敌减少了序列化和编码。 大部分序列化都在RPC因此,应减少应用之间的应用RPC调用,一个常见的方案是合并部署,合并部署多个相关性强的应用。比如两个原本在不同机器上的不同应用合并部署在同一台机器上。tomcat而且不能走本机socket,这样可以避免序列化。

3.Java极致优化 大部分请求直接在Nginx服务器或者Web代理服务器返回可以减少数据的序列化和反序列化,java层只处理少量数据的动态请求。 减少数据。事实上,有两个地方特别影响性能。一是服务端在处理数据时不可避免地会将字符转换为字节,二是 HTTP 请求时要做 Gzip 压缩,还有网络传输的耗时,这些都和数据大小密切相关。 数据分级。也就是说,为了确保第一个屏幕是第一个,重要的信息是第一个,次要的信息是异步加载,以提高用户获取数据的体验

4.并发读优化 目前这里采用的加锁方案是通过的tair除此之外,是否还有其他吗? 应用层LocalCache,将与商品相关的数据缓存杀系统的单机上。一般分为动态数据和静态数据。 静态数据:比如商品标题、描述等不会改变的数据,在秒杀之前全部推到秒杀机上,并缓存到秒杀结束。 动态数据:例如,库存等动态数据将被收集”被动失效“的方式缓存一定时间(一般是数秒),失效后再去缓存拉取最新的数据。 这里有个常人无法理解的事情,像库存这种频繁更新的数据,一旦数据不一致,会不会导致超卖? 这就要用到前面介绍的数据的分层校验原则,读的场景可以允许一定的脏数据,因为这里的误判只会到你少量原本无库存的下单请求被误认为有库存,可以等到真正写数据时再保证最终的一致性,通过在数据的高可用性和一致性之间平衡,来解决高并发的数据读取问题。

此外,要做好优化,你还需要做好应用基线,比如性能基线(何时性能突然下降)、成本基线(去年双 11 用了多少台机器)、链路基线(我们的系统发生了哪些变化),你可以通过这些基线持续关注系统的性能,做到在代码上提升编码质量,在业务上改掉不合理的调用,在架构和调用链路上不断的改进。

性能优化的核心就一个字-减

如果还继续减的 1:异步化-减少等待响应的时间 2:降日志-减本地磁盘的交互 3:多级缓存-再减少获取数据路径 4:减功能-非核心功能或后补功能去掉

分库分表,ID路由

第六章 秒杀系统减库存设计的核心逻辑

购买一般分两步:下单和付款

减库存一般有如下几个方式: 下单减库存:可能存在的问题是恶意下单,从而影响卖家的商品销售 付款减库存:可能存在的问题:库存超卖,因为下单和付款是割裂的,可能会造成很多卖家下单成功,导致下单数量超出库存,只能在付款时提示失败,影响购物体验。 预扣库存:将两次操作合并,下单时先预扣,在规定时间内不付款再释放库存,即采用“预扣库存”的方式,虽然一定程度上缓解了上面的问题,但是针对恶意下单的情况,虽然把有效付款时间设置为10分钟,但是恶意买家完全可以十分钟后再次下单,或者采用一次下单很多件的方式来把库存减完。针对这种情况,解决办法还是要结合安全和反作弊措施制止。 例如,给经常下单不付款的买家进行识别打标(可以在被打标的买家下单时不减库存)、给某些类目设置最大购买件数(例如,参加活动的商品一人最多只能买 3 件),以及对重复下单不付款的操作进行次数限制等。针对“库存超卖”这种情况,在 10 分钟时间内下单的数量仍然有可能超过库存数量,遇到这种情况我们只能区别对待:对普通的商品下单数量超过库存数量的情况,可以通过补货来解决;但是有些卖家完全不允许库存为负数的情况,那只能在买家付款时提示库存不足。

大型秒杀系统中如何减库存? 确定适合的场景:下单减库存

下单减库存在数据一致性上,主要就是保证大并发请求时库存数据不能为负数,也就是要保证数据库中的库存字段值不能为负数,一般有以下几种解决方案: 在应用程序中通过事务来判断,保证减库存后库存不能为负数; 直接设置数据库的字段数据为无符号证书,这样减库存字段值小于零时会直接执行SQL语句报错; 使用case when 判断语句 UPDATE item SET inventory = CASE WHEN inventory >= xxx THEN inventory-xxx ELSE inventory END

秒杀系统减库存的极致优化 后续整理

第七章 Plan B

高可用建设应该从哪里着手

架构阶段: 架构阶段主要考虑系统的可扩展性和容错性,要避免系统出现单点问题,做好多机房单元化部署,异地容灾。在系统不同阶段选择不同的设计结构,比如qps只有10时,可能简单增删改查就足够了,当系统流量上去之后,需要分布式以及微服务拆分等措施来保障系统的高可用性。

编码阶段: 编码阶段最重要的是保障代码的健壮性,有防御式编程的思想,例如涉及远程调用问题时,设置合理的超时退出机制,防止被其他系统拖垮,也要对调用的返回结果集有预期,防止结果超出系统处理范围,对自己负责的系统要有足够的了解,哪些服务,哪些数据是核心服务、核心数据,哪些是可被降级、异常可被允许的,哪些服务需要兜底数据,保障服务24小时正常可用。

测试阶段: 要保障测试用例的覆盖度,常用极端数据对系统健壮性进行测试。

发布阶段: 分批发布,安全生产环境小流量验证,发布阶段要支持回滚机制。

运行阶段: 监控是核心,要能够及时发现并定位问题。

故障阶段: 故障发生时首先要考虑的是止损,先止损,再恢复服务,最后再对数据清洗。

特殊时期: 如大促、秒杀等场景,参考全篇。

当应用无法承受大流量洪峰时,该如何针对运行阶段进行处理? 三种方式:降级、限流和拒绝服务

1.降级 降级预案制定的前提是,我们要对自己负责的系统足够熟悉,包括核心功能、依赖的第三方服务、依赖服务按照重要登记进行分层划分。降级一般分为两种类型:业务降级、数据降级和服务降级。 业务降级是针对的是某个产品而言,将部分产品功能进行降级,比如淘宝双十一大促时节,核心流量聚焦在少数核心功能上,此时可以将部分非核心产品下线,提升系统抵抗力。 数据降级指的是返回数据总量进行一定程度上的降级、比如返回歌曲总数由50条降级为10条,数据量的减少也就意味着数据编码耗时会降低、线程处理时间降低,cpu降低。 服务降级指的是系统依赖的第三方服务进行降级,比如获取商品详情,本身商品会获取除商品本身之外的其他附加信息(如商品评价,依赖评论系统),这些第三方服务的调用会增加额外的网络开销,同时更多的数据意味着数据序列化和编码也需要耗费更多的cpu,影响性能。 所以在系统达到一定容量时,我们需要针对不同的系统设立不同的“预案”,它是一个有目的,有计划的执行过程,可以通过预案系统来实现降级。

2.限流 相比起降级这种方式,限流行为更加极端一些,当系统容量到达瓶颈时,降级也无法解决问题,此时可以通过限制一部分流量来保护系统。 系统上线前,我们必须要通过压测提前对自己的系统水位有一个预估,将限流阈值控制在这个水位线之下。 常见的限流手段有基于QPS和线程数的限流。可以在java层做,更好的是在上层web服务器,如nginx中做限流。

3.拒绝服务 拒绝服务是抵挡流量洪峰的最极端的一种手段,用以防止最坏的情况发生,防止因服务器压垮而长时间彻底无法提供服务。比如在nginx上设置过载保护,当机器负载达到某个值时直接拒绝http的请求,并返回503错误码。

nigin网关层 + lua脚本,读取tair/redis/diamond,限流动态化配置 抽奖系统防超卖 第一步,拿商品key 第二步,写db,key是唯一主键,写中奖纪录时其他key写不进去 淘宝的直接db减库存保证,问题是商品量大,并发高时,写数据库只写这一行的数据,db压力非常大,排队无队可排

一个key,1000万人,怎么搞? 一个key,分到1000个桶,999个是空的,只要奖品发出去就ok,不在乎先后时间顺序

vip商品量大的,通过redis原子锁去搞

标签: 压力变送器tm21jhs保电阻电缆

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台