当前位置: 首页 > 科技观察

面试官:给我画一下秒杀系统的架构图吧!

时间:2023-03-21 10:15:23 科技观察

本文转载自微信公众号《Java教程》,作者九灵。转载本文请联系Java教程公众号。泪,不忍回首!博主毕业4年了,最近秋招开始了。每次回想起自己的秋招,那时候都觉得特别可惜(美食是原罪)。当时我的简历上只有一个项目在农资电商平台上,那个时候秒杀系统还没有那么流行(简历人均秒杀系统)。第一次微众面试,我的套路文其实还不错,但是我的项目只是一个单机系统,分布式?微服务?在酒店房间里,面试官笑着看着我,说让我先画下我项目中的农资电商平台。我脑子嗡嗡作响,什么?怎么画,就一个Android系统,一个前端页面,一个后台系统?它可能看起来像这样。太简单了。我应该让它更复杂吗?或者,我可以称之为结构吗?就这样,我犹豫了一下,连毛线都没有画……我记得画过这样的东西。.不出所料,放个屁~这东西有点不一样,不说了,尴尬~第二次微众面试第二次微众面试,毕业快一年了,抱着试一试的心态,发现我得到了一个学姐的内推,我当时在干什么,我在做爬虫。公司离微众比较近,就在金蝶。下班后,我溜过去和面试官聊了八篇八卦。好家伙,过了一会儿,我拿出一张纸:来画你现在的爬虫。系统架构图!当时系统的部署架构是这样的,比上面的简单一点。但是,我就是不会画!!!我觉得太简单了!!这东西能叫建筑吗?摊牌,我不会画!现在想想,真的好委屈啊少年!那我们现在回过头来看,怎么画呢?单体系统部署架构图爬虫系统分层架构图爬虫系统业务架构图架构图从上面各个方向的架构描述来看,其实即使是单体系统也能画出不一般的架构图!(为什么我当时做不到!)最近在看建筑相关的内容(刘德华的课)。在4+1的视图中,从很多方面描述了我们的系统,可以参考下面的描述,你们的秒杀系统的架构是怎样的?不管你的简历单系统多牛逼,我估计你的服务大部分都是长期这样的,如果你猜对了,点开关注,只有浏览器是分布式的。那我应该怎么描述我的单系统呢?架构设计的三大原则:简洁原则、适度原则、进化原则,每一个原则都符合我校制定的秒杀体系!!简单性原则:一个系统就可以满足我们没有太多的中间件依赖我们秒杀服务所有动作的合适原则:在我们的实际项目中,单体系统是最合适的。(主要是没钱!拆分服务、引入中间件、部署集群都是要花钱的!)进化原理:这个比较好理解。没有一出生就固定的系统架构。随着时间的推移,业务需求也在不断发展。总结:我们架构的优点:成本低,系统复杂度低,维护成本低,问题定位快缺点:稳定性差,并发度低,扩展性差等,在梳理架构的时候,每一种方案都有它的优缺点,所以你需要了解您当前解决方案的优缺点。只有这样才能更好的把你的系统展示给面试官!服务拆分是个好人,我参加了一个科技创新大赛,资金到位,可以多买机器,所以不能优化服务,拆分出一个微服务系统!有什么动作我们采取了这种服务拆分架构?静态资源隔离(CDN加速)代理服务器(Nginx)服务拆分,应用独立部署服务rpc通信(rpc框架&注册中心)1.前后在单体系统中,我们的静态资源(Html,JS,CSS和IMG)可能都通过我们的服务器返回。问题是:前端代码维护成本比较高(全栈开发成本也高)前端代码发布需要整个系统发布服务器带宽,请求资源占用等,那么带来的好处前后端分离明显:代码独立维护(低耦合),发布成本低(高效率),前后端通过接口加速访问交互式动态数据CDN资源,减少后台-端服务压力大(高性能)2.反向代理反向代理的作用比较明显。由于我们的服务是拆分成多个的,所以在和前端交互的时候,我们需要提供一个Universal的入口。而这个条目就是我们的反向代理服务器(Nginx)。例如:服务域名:https://www.jiuling.com,根据restful规范,我们可以通过https://www.jiuling.com/user/1.0将请求转发到用户服务的登录界面/登录。3、进程间通信随着服务的拆分,一些功能的实现会涉及到服务之间的相互调用。例如:在常见的实现方案中,我们会使用注册中心和RPC框架,来实现这个能力。而我们比较常用的实现是zookeeper&dubbo。为什么要使用RPC框架?当我们提到使用RPC框架时,你有没有想过为什么要使用RPC框架?每个服务都提供一个RESTful接口。不也可以完成服务间通信吗?这里我们需要比较一下RPC和RESTful的区别:数据报文小&传输效率快:RPC在传输协议中简化了一些必要的头部信息,从而加快了传输效率。开发成本低:例如Dubbo框架封装了服务间调用的逻辑(如:反射、建立连接、超时控制等),只需要开发相应的接口和数据模型。服务治理:在分布式场景下,我们有多个服务提供者,因此我们需要处理服务健康、负载均衡和服务流控,而这些能力都在rpc&注册中心架构下。已经很满意了。说完优点再分析一下RPC的缺点:强耦合:相对于RESTful,RPC框架在跨语言场景下的实现难度更大。而且版本依赖性比较强。服务脱离当前内网环境后,无法正常提供服务,迁移成本高。内网调用:RPC比较适合内网传输,但是在公网环境下就没那么安全了。分布式微服务在之前版本的服务拆分中,我们根据不同的业务边界和功能职责划分了多个子系统,对于不同的系统,它所承受的负载压力是不同的,例如:订单服务,每个请求的处理时间都比较长(其他服务压力不大)。为了增加我们的订单量,我们只能扩大订单服务。这就是我们在服务拆分上带来的好处,性能使用率提升!从上图中,我们可以看到一些服务有不同的鬼影。每个方块都可以理解为一台机器。在这个架构中,为了保证我们的订单成功率,以及下单量,我们主要将服务器集中在订单服务上。在此之前,先看看我们的中间件集群部署:mysql主从架构:读写分离,减轻主库压力,保证数据可以正常写入,保证订单数据入库.zookeeper主从架构:保证注册中心可用,避免造成整个链路的雪崩。Redis哨兵集群:避免redis宕机导致大流量直接打到数据库。总结到此为止,一般我们自己开发的系统基本完成了整个秒杀系统的演进。可能大家一直有一个疑问,为什么我们最熟悉的MQ少了呢?在整个调用环节,我会以同步调用的形式来描述这个秒杀系统的架构,因为这已经满足了我们现在的流量需求了,在架构设计的原则中,提到过,适度原则,适度原则的进化。在满足流量需求的现状下,需要考虑消息中间件的引入。有什么问题?有哪些问题需要解决?权衡利弊之后,是时候让我们决定是否使用这个方案了。高性能在上述架构的演进过程中,我们通过服务拆分、垂直扩展、分布式部署等方式提升了我们架构的性能和稳定性,足以满足我们在自研阶段的架构演进我们的流量有吸引力,但是如果我们想继续优化我们的系统,提高服务性能,我们可以从以下几个方面进行优化:资源预热缓存预热异步调用1.资源预热在上面的服务拆分阶段,我们会提供当说到动静资源分离,这里的静态资源包括:html、js、css、img等。在我们活动阶段,我们可以通过后台管理系统,加速资源访问。资源预热:通过预加载资源到CDN回源:CDN找不到资源后,会触发源站(商品服务)调用查询对应的资源。如果资源在源站存在,则返回CDN做进一步处理。缓存。OSS:实际存储静态资源的服务(指阿里云OSS)上面已经多次提到,在引入一项技术的时候,需要同时考虑它的优势和劣势,那么CDN有哪些风险呢?成本:更直接的,就是要花很多钱!带宽:大流量访问下,CDN能不能支撑这么多带宽,每台服务器能支撑的流量是有限的,需要考虑CDN能不能支撑业务流量。CDN命中率:在CDN命中率较低的情况下,比如活动图片,每小时会更换一次,每次更换图片都会触发回源操作,资源访问效率会下降到这次。2.缓存预热与上面的静态资源加速相比,动态数据需要通过缓存来优化性能。老生常谈了,为什么redis这么快?单线程(redis的性能瓶颈不在这里,所以这不是优势)多通道I/O多路复用模型的数据结构简单,基于内存操作。引入redis带来的风险主要包括:Reids宕机:在单机部署的情况下,会导致大量服务调用超时,最终造成服务雪崩。可以通过Sentinel集群进行优化。缓存击穿:在大流量情况下,缓存MISS和缓存过期会导致请求穿透到数据库。如果数据库承受不住压力,就会造成服务雪崩。可以使用布隆过滤器进行优化。数据一致性:缓存数据和DB之间的数据一致性需要通过更新策略来保证。3.异步调用异步方式,将减库存成功的用户通过消息发送给订单服务,用于后续下单。所有产品都可以在短时间内销售。整体流程如下图所示:为什么MQ异步调用可以提高我们服务的吞吐量?主要是我们通过异步调用,传递了消息,完成了这次的请求处理。那么性能瓶颈就从订单服务转移到了秒杀服务。通过减少调用依赖,提高了整体服务的吞吐量。MQ带来的常见问题:数据一致性和重复消费:由于生产者重复发送消息,或者消费慢,导致消息重复推送。需要加锁,消费幂等,保证正常消费。消息堆积:当生产能力远大于消费能力时,会导致消息堆积。MQ可用性:在MQ宕机的情况下,需要支持同步调用切换。这里就不做详细介绍了,后面会写一篇MQ相关的文章。看到这里高可用不容易,感谢大家的支持。这里关于易用性,我之前写过一篇文章#?-B站跳楼了,我A站怎么回事?如果你有兴趣,你可以看看。高可用主要可以通过以下方式实现:动态扩展:根据业务压力,对不同的业务进行动态扩展。限流断路器:请参考我之前的文章:#《高可用实战》-B站跳楼了,我A站怎么回事?异地多动:通过多房间部署,躲避物理攻击!同城双活部署不同区内机房采用专网相连。两个机房之间的距离一般为几十公里,网络传输速度与同一个机房??相差无几,降低了系统复杂度和成本。这个模型无法解决极端灾害情况,比如某个城市的地震、洪水。这种方法用于解决一些常规故障,如机房火灾、停电、空调故障等。上述模型中异地居住,没有办法解决城市级服务容灾,比如洪水、地震等情况。这个问题可以通过异地部署多活来解决。但是每种方案都有优点和缺点,所以异地多活的缺点主要体现在网络传输和数据一致性的问题上!跨城异地的主要问题是网络传输延迟,比如北京到广州,正常情况下的RTT(Round-TripTime往返延迟)是50毫秒。遇到网络波动等情况,会上升到500毫秒甚至1秒,就会出现丢包问题。物理距离必然导致数据不一致,必须从“数据”的特性来解决。如果是需要强一致性的数据(比如存款余额),不可能多做异地工作。图片地址:draw.io原图