目录
前言
秒杀大家都很熟悉,自从2011年出现以来,无论是双十一、双十二还是12306抢票,秒杀场景可以随处可见。什么是秒杀?简单的说,秒杀就是同一时刻大量请求争抢购买同一个商品并完成交易的过程。从架构的角度上考虑,秒杀系统本质就是一个高性能、高一致、高可用的三高系统。而打造并维护一个超大流量的系统需要关注哪些地方?
整体思考
首先从三高的维度考虑,整体思考问题。秒杀无外乎解决两大核心问题,一是并发读,一是并发写,对应到架构设计,就是高性能、高一致、高可用的要求,关于秒杀系统的设计思考,基于三层依次推进,简述如下——
- 高性能。秒杀涉及高并发读和高并发写的支持,如何支撑高并发,如何抵抗IOPS?核心优化理念:高并发读就尽量“少读”或者“读少”,高并发写就数据拆分。可以从动静分离、热点优化以及服务端性能优化三个方面进行考虑。
- 高一致。秒杀的核心是关注商品的库存,有限的商品在同一时间被多个请求同时扣减,而且要保证准确性,显而易见这是一个难题,如何做到既不多又不少?本文将从行业通用的几种减库存的方案切入,讨论一致性设计的核心逻辑。
- 高可用。大型分布式系统在实际运行过程中面对的情况是非常复杂的,业务流量突增、依赖服务的不稳定、应用自身的瓶颈、物理资源的损坏等等方方面面都会对系统运行带啦大大小小的冲击。如何保障应用在复杂情况下还能高效运行,如何预防和应对突发问题,系统设计应该从哪方面着手?本文将从架构落地的全局角度进行思考。
高性能
1、动静分离
大家可能会注意到,在秒杀过程中是不需要刷新整个页面的,只有时间在不停的跳动。这是因为一般都会对大流量的秒杀系统做系统的静态化改造,即数据意义上的动静分离。动静分离:1、数据拆分;2、静态缓存;3、数据整合。
1.1、数据拆分
动静分离的首要目的是将动态页面改造成适合缓存的静态页面。因此第一步就是分离出动态数据,主要从以下两个方面进行考虑
1、用户。用户身份信息包括登录状态以及登录画像等,相关要素可以单独拆分出来,通过动态请求获取,与之相关的广平推荐,如用户偏好、地域偏好等,同样可以通过异步加载的形式获取。
2、时间。秒杀时间是由服务端统一管控的,可以通过动态请求获取。
1.2、静态缓存
分离出静态数据之后,第二部就是将静态数据进行缓存,由此就衍生出两个问题:1、如何缓存;2、在哪里缓存
1.2.1、如何缓存
静态化改造的一个特点是直接缓存整个HTTP连接而不是仅仅缓存静态数据,如此一来,Web代理服务器根据请求的URL,可以直接取出对应的响应体直接返回给前端用户,响应过程不需要重组HTTP协议,也不需要解析HTTP的请求头,而作为缓存键,URL的唯一化是必不可少的,只是对于商品系统,URL天然是可以基于商品ID来进行唯一标识的。
1.2.2、哪里缓存
静态数据缓存有以下三种方式:
1、浏览器
2、CDN
3、服务器
浏览器首先是第一选择,但是用户的浏览器是不可控的,主要体现在用户不主动刷新,系统很少主动的把消息推送给用户(注意,当讨论静态数据时,潜台词是“相对不变”,言外之意是“可能会变”),如此可能会导致用户在很长的一段时间之内看到的数据是错误的数据。相对于秒杀系统,保证缓存可以在秒级时间内失效是不可或缺的。
服务端主要进行逻辑计算和加载,本身并不擅长处理大量连接,每个连接消耗内存也比较大,同时Servlet容器解析HTTP较慢,容易侵占逻辑计算资源;另外,静态资源下沉至此也会拉长请求路径。
因此通常将静态资源存在CDN,其本身更擅长处理大并发的静态文件请求,既可以做到主动失效,又离用户尽可能的近,同时规避java语言层面上的弱点。需要注意的是,使用CDN有以下几个问题需要解决。
1、失效问题。任何一个缓存都应该是有时效性的,尤其是对于秒杀场景。所以,系统需要保证全国各地的CDN在秒级时间内失效掉缓存信息的问题,这实际对CDN失效系统是要求很高的。
2、命中率问题。高命中是缓存系统最核心的性能要求,不然缓存就失去了意义。如果将数据放在全国各地的CDN,势必会降低请求命中同一个缓存的可能性,那么命中率就成了问题。
因此,将缓存数据放在全国各地的CDN节点是不太现实的,失效问题、命中率问题都会面对比较严峻的挑战。更为可行的方案是选择若干CDN节点进行静态化改造,节点的选取通常需要满足一下几个条件:
1、临近访问量集中的地区
2、距离主站较远的地区
3、节点与主站间网络质量良好的地区
基于以上因素,选择CDN的二级缓存是比较合适的,因为二级缓存的数量偏少,容量也更大,访问量相对集中,这样就可以较好的解决缓存失效的问题和命中率的问题,是当前比较理想的CDN优化方案。部署方式如下图所示:

1.3、数据整合
分离出动静态数据之后,前端如何组织数据就是一个新的问题,主要在于动态数据加载处理,通常有两种解决方案:ESI(Edge Side Includes)方案和 CSI(Client Side Include)方案。
1、ESI方案:Web代理服务上请求动态数据,并将动态数据插入到静态页面中,用户看到页面时已经是一个完整的页面。这种方式对于服务性能要求比较高,但是用户体验也是比较好。
2、CSI方案:Web代理服务器上只返回静态页面,前端单独发起一个异步JS请求动态数据。这种方式对于服务器性能比较友好,但是用户体验稍差。
1.4、小结
动静分离对于性能的提升,抽象起来只有两点:
一是数据要尽量的少,以便减少没必要的请求,
二是路径要尽量的短,以便提高单次请求的效率。
具体的方案都是基于这个大方向进行的。
2、热点优化
热点分为热点操作和热点数据,以下进行分开讨论
2.1热点操作
零点刷新、零点添加购物车、零点下单等都属于热点操作。热点操作是属于用户行为,不容易改变,但是可以做一些限制性的保护,比如用户频繁刷新某一个页面时进行阻断提示。
2.2热点数据
热点数据的处理可以分为三步处理
1、热点识别
2、热点阻隔
3、热点优化
2.2.1热点识别
热点数据分为静态热点数据和动态热点数据,具体如下
1、静态热点数据:能够提前预热的热点数据。大促前夕,可根据大促的行业特点、活动商家等维度信息分析出热点商品,或者通过卖家报名的方式提前筛选;另外还可以通过技术的手段提前预测,例如对买家每天访问的商品进行大数据计算,然后统计出TOP N的商品,即为热门商品。
2、动态热点数据:无法提前预热的热点数据。冷热数据往往是随着实际的业务场景而不断的发生变化,尤其是如今直播卖货模式的兴起——带货商临时做一个广告,就有可能导致一件商品在短时间内大量购买。由于此类商品在日常访问中比较少,即使在缓存系统中一段时间之后也会被逐出或过期掉,甚至在DB中也是冷数据。瞬时流量的涌入,往往导致缓存被击穿,请求直接到达DB,引发DB压力过大。
因此秒杀系统需要实现热点数据的动态发现能力,一个常见的实现思路是:
1、异步采集交易链各个环节的热点key信息,如Nginx采集访问URL或Agent采集热点日志(一些中间件本身已经具备热点发现能力),提前发现潜在的热点数据。
2、聚合分析热点数据,达到一定规则的热点数据,通过订阅分发推送到链路系统,各系统根据自身需求决定如何处理热点数据,或限流或缓存,从而实现热点保护。
需要注意的是:
1、热点数据采集最好采用异步的形式,一方面不影响业务的核心交易链路,一方面可以保证采集方式的通用性。
2、热点发现最好做到秒级实时,这样动态发现才有意义,实际上也是对核心节点的数据采集和分析能力提出较高的要求
2.2.2热点隔离
热点数据识别出来之后,第一原则就是将热点数据进行隔离出来,不要让1%影响到另外的99%,可以基于以下几个层次实现热点隔离。
1、业务隔离。秒杀作为一种营销活动,卖家需要单独报名,从技术的角度上来说,系统可以对已知的热点做缓存预热。
2、系统隔离。系统隔离是运行时隔离,通过分组部署和另外的99%进行分离,另外秒杀可以申请单独的域名,入口层就能让请求落到不同的集群中。
3、数据隔离。秒杀数据作为热点数据,可以启用单独的缓存集群或者DB服务组,从而更好的实现横向或纵向能力扩展。
当前实现热点隔离的方式还是很多种方法。比如按照用户来区分,为不同的用户分配不同的cookie,入口层路由到不同的服务接口中;再比如,域名保持一致,但后端调用不同的服务接口;又或者在数据层给数据打标进行区分等等,这些措施的目的都是把已经识别的热点请求和普通请求区分开来。
2.2.3热点优化
热点数据隔离之后,也就方便对这1%的请求做针对性的优化,优化方式无外乎两种形式:
1、缓存:热点缓存是最有效的处理方式。如果热点数据做了动静分离,那么可以长期缓存静态数据。
2、限流:流量限制更多是一种保护机制。需要注意的是,各个服务需要时刻关注请求是否触发限流并及时进行review。
2.2.4小结
数据的热点优化和动静分离是不一样的,热点优化是基于二八原则对数据进行纵向拆分,以便进行针对性的处理。热点识别和隔离不仅仅对于“秒杀”这一种场景有意义,对其他的高性能分布式系统也具有参考意义。
3、系统优化
对于一个软件系统,提高性能可以有很多种手段,比如提升硬件水平、调优JVM性能,这里主要关注代码层面的性能调休——
1、减少序列化:减少java中的序列化操作可以很好的提升系统性能。序列化大部分在RPC阶段发生,因此应该尽量减少RPC调用,一种可行的方案是将多个关联性较强的应用进行“合并部署”,从而减少不同应用之间的RPC调用(微服务设计规范)。
2、直接输出流数据:只要涉及字符串的I/O操作,无论是磁盘I/O还是网络I/O,都比较耗费CPU资源,因为字符串需要转换成字节,而这个转换又必须查表编码。所以对于常用的数据,比如静态字符串,推荐提前编码成字节并缓存,具体代码就是通过OutputStream() 类函数从而减少数据的编码转换;另外热点方法toString()不要直接调用ReflectionToString实现,推荐直接硬编码,并且只打印DO的基础要素和核心要素。
3、裁剪日志异常堆栈:无论是外部系统异常还是应用本身异常,都会有堆栈打出,超大流量下频繁的输出完整堆栈,只会加剧系统当前负载。可以通过日志配置文件控制异常堆栈输出的深度。
4、去组件框架:极致优化要求下,可以去掉一些组件框架,比如去掉传统的MVC框架,直接使用Servlet处理请求。这样可以绕过一大堆复杂且用处不大的逻辑处理,节省毫秒级的时间,当前,需要合理评估业务或个人对框架的依赖程度。
4、总结
性能优化需要一个基准值,所以系统还需要做好应用基线,比如性能基线(何时性能才会突然下降)、成本基线(去年大促用了多少机器)、链路基线(核心流程发生了那些变化),通过这些基线持续关注系统性能,促使系统在代码层面上持续提升编码质量、业务层面及时踢出不合理的调用、架构方面不断优化改进。
一致性
秒杀系统中,库存是关键数据,卖不出去是个问题,超卖更是一个问题,秒杀场景下的数据一致性问题,主要体现在库存的扣减的准确性问题。
1、减库存的方式
电商场景下的购买过程一般分为两步:下单和付款。“提交订单”即为下单,“支付订单”即为付款。基于此设定,减库存一般有以下几种实现方式:
1、下单减库存。买家下单后,扣减商品库存。下单减库存是最简单的减库存的方式,也是控制最为精准的一种方式。
2、付款减库存。买家下单后,并不立即减少库存,而是等待付款成功之后才会真正扣减库存。但是,因为付款时才扣减库存,如果并发比较高的情况下,可能出现买家下单后不能付款的情况,因为商品已经被其他买家买走了。
3、预扣库存。这种方式相对比较复杂一些,买家下单之后,库存为其保留一段时间(如30分钟),超过这段时间,库存会自动释放,释放后其他买家可以正常购买。
能够看到,扣减库存的方式是基于购物过程的多阶段进行划分的,但无论是在下单阶段还是在付款阶段,都会存在一些问题,下面进行具体的分析。
2、减库存的问题
2.1下单减库存
优势:用户体验最好。下单减库存是最简单的库存扣减方式,也是控制最为精确的一种。下单时可以直接通过数据库事务机制控制商品库存,所以一定不会出现已下单确不能付款的情况。
劣势:可能卖不出去。正常情况下,买家下单之后付款的概率非常高,所以不会有太大的问题。但有一种场景例外,就是当卖家参加某个促销活动时,竞争对手通过恶意下单的方式将该商品全部下单,导致库存清零,那么这就不能正常售卖了——要知道,恶意下单的人是不会真正付款支付的,这就是“下单减库存”的不足之处。
2.2付款减库存
优势:一定实际售卖。“下单减库存”可能会导致恶意下单,导致库存清零,从而影响卖家的商品销售,“付款减库存”由于是需要付款成功之后才会真正扣减库存,可以有效避免“下单减库存”所带来的影响。
劣势:用户体验较差。用户下单之后,并不一定实际付款,假设有100个商品,就有可能出现200个人下单成功的情况,因为下单时不会扣减库存,所以就有可能出现下单成功数远远超过真正的商品库存数量的情况,这种情况尤其会发生在大促的热门商品上。如此一来就会导致很多买家下单成功后确不能付款的问题,购物体验自然就会比较差。
2.3预扣库存
优势:缓解了以上两种方式的问题。预扣库存实际上就是“下单减库存”和“付款减库存”两种方式的结合,将两次操作进行前后关联,下单时预扣库存,付款时释放库存。
劣势:并没有彻底解决以上的问题。比如针对恶意下单的场景,虽然可以把有效付款时间设置为10分钟,但恶意买家完全可以在10分钟之后再次下单。
2.4小结
扣减库存的问题主要体现在用户体验和商业诉求两方面,其本质原因在于购物过程存在两步甚至多步操作,在不同阶段扣减库存,容易存在被恶意利用的漏洞。
3、实际如何减库存
业界最为常见的就是预扣库存。无论是外卖点餐还是电商购物,下单后一般都有“有效付款时间”,超过该时间订单自动释放,这就是典型的预扣库存的方案。但如上所述,预扣库存还需要解决恶意下单的问题,保证商品卖得出去;另外,如何避免超卖,也是一个痛点。
1、卖的出去。恶意下单的解决方案主要还是结合安全和反作弊措施来制止。比如,识别频繁下单不付款的买家进行打标,这样可以在打标买家下单时不扣减库存;再比如为大促销商品设置单人最大购买数量,一人最多买N件商品;又或者对重复下单不支付的行为进行次数限制阻断等。
2、避免超卖。库存超卖的情况实际分为两种。对于普通商品,秒杀只是一种大促手段,即使库存超卖,商家也会通过补货来解决超卖的问题;而对于一些商品,秒杀作为一种营销手段,完全不允许库存为负的情况,也就是在数据一致性上,需要保证大并发请求下数据库库存字段不能为负,一般有多种解决方案:一是通过事务来判断,即保证扣减库存后库存不能为负,否则就回滚;二是直接设置数据库字段类型为无符号整数,这样一旦库存为负就会在执行SQL时报错;三是使用CASE WHEN判断语句:sql UPDATE item SET inventory = CASE WHEN inventory >= xxx THEN inventory-xxx ELSE inventory END<br />
业务手段保证商品卖得出去,技术手段保证商品不会被超卖,库存问题从来就不是一个简单的技术难题,解决问题的视角是多种多样的。
4、一致性性能优化
库存是个关键数据,更是一个热点数据。对系统来说,热点的实际影响就是“高并发读”和“高并发写”,也就是秒杀场景下的最为核心的技术难题。
4.1高并发读
秒杀场景解决高并发读的问题,关键词是“分层校验”。即在读链路中,只进行不影响性能的检查操作,如用户是否具有秒杀资格、商品状态是否正常、用户答题是否正确、秒杀是否已经结束、是否非法请求等,而不做一致性校验等容易引起性能瓶颈的校验操作;直到写链路操作时,才对库存做一致性检查,在数据层保证最终准确性。
因此在分层校验的设定下,系统可以采用分布式缓冲设置LoadCahed来抵抗高并发读。即允许读场景下出现一定的脏数据,这样只会导致少量原本无库存的下单请求被误认为有库存的,等到真正在写数据库时再保证最终一致性,由此可以做到高可用和一致性之间的平衡。
实际上,分层校验的核心思想是:不同层次尽可能的过滤掉无效请求,只在“漏斗”最末端进行有效处理,从而缩短系统瓶颈的影响路径。
4.2高并发写
高并发写的优化方式,一种是更换DB选型,一种是优化DB性能,下面对这两种方式分别介绍:
4.2.1更换DB选型
秒杀商品和普通商品的扣减库存是有差异的,核心区别在于数据量级小、交易时间短,因此可以把秒杀商品的库存直接放在缓存系统中进行处理,也就是在一个带有持久化功能的缓存中进行扣减库存,比如Redis。
如果扣减库存的逻辑比较单一的话,比如没有复杂的SKU库存和总库存这种联动关系的话,个人认为是完全可以通过缓存来实现。但是,如果有比较复杂的扣减库存逻辑存在,或者需要使用到事务,那就必须要在数据库中完成扣减库存的操作。
4.2.2优化DB性能
库存数据落地到数据库其实就是一行存储(Mysql),因此有大量的线程来竞争InnoDB行锁。但并发数越高,等待线程就越多,TPS下降,RT上升,吞吐量会严重受到影响——注意,这里假设数据库已经基于【性能优化】完成数据隔离,以便讨论聚焦。
解决并发锁的问题,有两种方式:
1、应用层排队。通过缓存加入集群分布式锁,从而控制集群对数据库同一行操作的并发度,同时也能控制单个商品占用数据库连接池的数量,防止热门商品占用过多的数据库连接。
2、数据层排队。应用层排队是有损性能的,数据层排队才是最理想的实现方案。业界中,阿里的数据库团队开发了针对InnoDB层上的不定程序(patch),可以基于DB层对单行记录做并发排队,从而实现秒杀场景下定制优化——注意,排队和锁竞争是有区别的,如果熟悉Mysql的话,就会知道InnoDB内部的死锁检测,以及Mysql Server和InnoDB的切换都是非常消耗性能的。另外阿里的数据库团队还做了很多其他方面的优化,如COMMIT_ON_SUCCESS和ROLLBACK_ON_FAIL的补丁程序,通过在SQL中加入提示(hint),实现事务不需要等待实时提交,而是在数据执行完最后一条SQL后,直接根据TARGET_AFFECT_ROW的结果来进行提交或者回滚,减少网络等待时间(毫秒级别)。目前阿里已将包含这些补丁的Mysql进行开源:AliSQl
4.3小结
高并发读和高并发写的两种处理方式大相径庭。高并发读的优化空间更大一些,而高并发写的瓶颈一般都在存储层,优化思路的本质还是基于CAP理论作为平衡。
5、总结
当然,扣减库存还有存在很多细节性的问题,例如预扣库存超时后如何进行回补,再比如第三方支付如何保证扣减库存和付款时的状态一致性,这些也是很大的挑战。
高可用
盯过秒杀流量监控的话,会发现它不是一条蜿蜒而起的曲线,而是一条挺拔的直线,这是因为秒杀请求高度集中于某一特定的时间点。这样一来就会造成一个特别高的零点峰值,而对资源的消耗也几乎是瞬时的。所以秒杀系统的可用性保护是不可或缺的。
1、流量削峰
对于秒杀的目标场景,最终能够抢到商品的人数是固定的,无论是100人和10000人参加的结果都是一样的,即有效请求额度是有限的。并发度越高,无效请求也就越多。但秒杀作为一种商业营销手段,活动开始之前都希望有更多的人来刷新页面,只是真正开始之后,秒杀请求不是越多越好。因此系统可以设计一些规则,认为的延缓秒杀请求,甚至可以过滤掉一些无效请求。
1.1答题
早期的秒杀只是简单的点击秒杀按钮,后来才增加了答题。为什么要增加答题呢?主要通过提升购买的复杂度,达到两个目的:
1、防止作弊。早期秒杀器比较猖獗,存在恶意买家或者竞争对手使用秒杀器扫货的情况,商家没有达到营销的目的,所以增加答题来进行限制。
2、延缓请求。零点流量的起效时间是毫秒级别的,答题可以认为拉长峰值下单的时长,由之前的<1s延长到<10s。这个时间对于服务端是非常重要的,会大大减轻高峰期并发压力;另外,由于请求具有先后顺序,答题后置的请求到来可能已经没有库存了,因此,根本无法下单,此阶段落在数据库层面上真正的写也就非常有限了。
需要注意的是,答题除了做正确性验证,还需要对提交时间做验证,比如<1s认为人为操作的可能性比较小,可以进一步防止机器答题的情况。
答题目前已经使用的非常普遍了,本质是通过限制入口层流量,从而让系统更好的支撑瞬时峰值。
1.2排队
最为常见的削峰方案就是使用消息队列,通过把同步的直接调用转换成异步的间接推送缓冲瞬时流量。除了消息队列,类似的排队方案还有很多,比如:
1、线程池加锁等待
2、本地内存蓄洪等待
3、本地文件序列化写,再顺序读
排队方式的弊端也是显而易见的,主要有以下两点:
1、请求积压。流量高峰如果长时间持续,达到队列的水位上限,队列同样会被压垮,这样虽然保护了下游系统,但是和请求直接丢弃没有什么本质区别。
2、用户体验。异步推送的实时性和有序性自然是比不上同步调用,由此可能出现请求先发后至的情况,影响部分敏感用户的购物体验。
排队本质是在业务层将一步操作转变成两步甚至多步操作,从而起到缓冲的作用,但鉴于此种方式的弊端,最终还是需要基于业务的量级和秒杀场景做出妥协和平衡。
1.3过滤
过滤的核心结构在于分层,通过不同层次过滤掉无效请求,达到数据读写的精准触发。常见的过滤主要有以下几层:
1、读限流:对读请求进行限流保护,将超出系统承载能力的请求过滤掉。
2、读缓存:对读请求做数据缓存,将重复的请求过滤掉。
3、写限流:对写请求进行限流保护,将超出系统承载能力的请求过滤掉。
4、写校验:对写请求做一致性校验,只保留最终有效数据。
过滤的核心目的是通过减少无效请求的数据I/O保障有效请求的I/O性能。
1.4小结
系统可以通过入口层的答题、业务层的排队、数据层的过滤达到流量削峰的目的,本质是在寻求商业诉求与架构性能之间的平衡。另外,新的削峰手段也是层出不穷,以业务切入居多,比如零点大促销时同步发放优惠券或发起抽奖活动,将一部门流量分散到其他系统,这样也能起到削峰的作用。
2、Plan B
当系统面临持续的高峰流量时,其实很难单靠自身调整来恢复状态的,日常运维没有人能够预估所有情况,意外总是无法避免。尤其是在秒杀这种特殊场景下,为了保证系统的高可用,必须设计一个plan B方案进行兜底。
高可用建设,其实是一个系统工程,贯穿在系统建设的整个生命周期。

具体的来说,系统的高可用建设涉及架构阶段、编码阶段、测试阶段、发布阶段、运行阶段以及故障发生时,逐一进行分析。
1、架构阶段:考虑系统的可扩展性和容错性,避免出现单点问题。例如多地单元化部署,即使某个IDC甚至地市出现故障,仍然不会影响系统正常运行。
2、编码阶段:保证代码的健壮性。例如,在RPC调用过程中,设置合理的超时退出机制,防止被其他系统拖垮,同时也要对无法预料的返回错误进行默认处理。
3、测试阶段:保证CI的覆盖度以及Sonar的容错率,对基础质量进行二次校验,并定期产出整体质量的趋势报告。
4、发布阶段:系统发布最容易暴露错误,因此要有前置的checkList模板、中置的上下游周知机制以及后置的回滚机制。
5、运行阶段:系统多数时间出于运行态,最重要的是运行时的实时监控,及时发现问题、精准报警并能提供详细数据,一边排查问题。
6、故障阶段:首要目标是及时止损,防止影响面扩大,然后定位原因、解决问题、最后恢复服务。
对于日常运维而言,高可用更多是针对运行阶段而言,此阶段需要额外加强建设,主要有以下几种手段:
1、预防:建立常态压测体系,定期对服务进行单点压测以及全链路压测,摸排水位。
2、管控:做好线上运行的降级、限流和熔断保护。需要注意的是,无论是降级、限流还是熔断保护,对业务都是有损的,所以在进行操作前,一定要和上下游业务确认好之后再进行操作。就拿限流来说,哪些业务可以限流、什么情况下可以限流、限流时长是多少、什么情况下恢复等,都需要和业务方反复确认。
3、监控:建立性能基线,记录性能变化趋势;建立报警体系,发现问题及时预警。
4、恢复:遇到故障能够及时止损,并提供快速的数据订正工具,不一定要好,但一定要有。在系统建设的整个生命周期中,每个环节都可能犯错,甚至有些环节犯的错,后面是无法弥补或者成本极高的。所以高可用是一个系统工程,必须放在整个生命周期中进行全面考虑。同时,考虑到服务的增长性,高可用更需要长期规划并进行体系化建设的。
3、总结
高可用其实是在说 “稳定性”,稳定性是一个平时不重要,但出了问题就要命的事情,然而它的落地又是一个问题——平时业务发展良好,稳定性建设就会降级给业务让路。解决这个问题必须在组织上有所保障,比如让业务负责人背上稳定性绩效指标,同时在部门中建立稳定性建设小组,小组成员由每条线的核心力量兼任,绩效由稳定性负责人来打分,这样就可以把体系化的建设任务落实到具体的业务系统中了。
个人总结
一个秒杀系统的设计,可以根据不同级别的流量,由简单到复杂打造出不同的架构,本质是各方面的取舍和权衡。当然,你可能注意到,本文并没有涉及具体的选型方案,因为这些对于架构来说并不重要,作为架构师,应该时刻提醒自己主线是什么。
同时也在这里抽象、提炼一下,主要是个人对于秒杀设计的提纲式整理,方便参考!
