掘金 后端 ( ) • 2024-06-11 10:44

平时没做过秒杀系统,但是面试又总被问秒杀系统该如何设计?
支撑十万,百万QPS的秒杀系统又该如何设计?

最近有小伙伴在面试的时候,被这两道题拷打了,因为没有提前做准备,所以回答的并不好。

所以小北今天就带大家体系化的梳理下,大厂级高并发的秒杀系统该如何设计。

带大家跳出程序员思维,从架构师的视角分析下,大厂级、高并发的秒杀系统该如何设计?

秒杀系统的三个问题

问题一:为什么需要秒杀系统?

简单来说,电商平台的主要工作是在线上撮合买卖双方的需求,完成交易。

为了促进销售,商场通常会搞各种促销活动,比如满减、折扣、赠品、会员优惠等。

秒杀活动的目的就是通过低价出售一些稀缺商品来吸引更多人流量,让更多人关注平台。

虽然有时候这些商品可能是亏本卖的,但吸引了人气,就能带来更多长期客户,这就是所谓的“赔本赚吆喝”。

问题二:京东、阿里巴巴等大平台都怎么重视秒杀系统?

大平台不仅卖普通商品,还有很多爆款商品。

爆款商品流量激增,而普通商品流量比较平稳。

如果不区分开这两类商品一起卖,会出现大问题,甚至导致平台崩溃。

这是因为秒杀流量来得突然且规模难以预测,如果混在一起,会严重影响普通商品的交易。

所以,京东、阿里这些大平台会单独建设秒杀系统,作为交易系统中的重要部分。

问题三:秒杀系统对我们有什么意义?为什么要学秒杀系统?

秒杀系统是互联网技术人员必须掌握的技能。

不论是京东、阿里这样的巨头,还是新兴的社区团购公司,都需要通过秒杀活动来吸引新用户和保持平台热度。

因此,学会设计和开发秒杀系统是每个IT技术人员的必修课。

秒杀系统涉及的高可用、高性能、高并发的设计思路,可以应用到其他系统中。

此外,很多面试也会考核秒杀系统的设计能力

插播一条:如果你近期准备面试跳槽,建议在cxykk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题、简历模板、算法刷题。

秒杀业务初步分析

每年的618、双11等都是电商平台的大型促销日,各种促销手段层出不穷,其中秒杀是最重要的一种。

像飞天茅台、华为手机、高端显卡这样的热门商品,经常会被抢购一空。

即使你没抢过,也可能听说过,这就是秒杀活动的影响力。

秒杀的主要目的是用价格有优势的稀缺商品,吸引大量用户,增加平台的流量,从而带来更多新用户。

如果再配合一些其他的促销手段,比如限制抢购资格给VIP用户,那平台还可以借此增加收入。

在如今这个流量为王的网络时代,能够搞好秒杀活动对电商平台非常重要。

因此,我们需要一个秒杀系统。

实现一个秒杀系统并不容易,要考虑很多方面:

1、首先,我们要了解秒杀活动的业务特点
2、其次,要清楚秒杀系统的请求流程,这样才能针对可能的瓶颈进行优化和设计

通常情况下,平台商家会拿出一些稀缺商品,提前在秒杀系统中设置好活动的开始和结束时间,以及投入的库存。

这些是秒杀的主要元素

活动开始后,用户可以通过活动入口(比如商品详情页或广告链接)进入结算页,点击下单,完成抢购。

整个过程如下:

预热期:为了管理流量,可以开放预约功能。在活动开始前一段时间内,让用户提前预约,只有预约成功的用户才能参与抢购。

活动期:用户通过入口进入秒杀页面,点击下单完成抢购。可以加上风控措施,比如校验用户资格,防止黄牛和有不良记录的用户参与。还可以限制个人在一段时间内的购买次数,确保更多人有机会抢到商品。

通过这些措施,我们可以灵活应对不同的业务场景,创造出适合自己的独特秒杀玩法。

秒杀系统的挑战

实现秒杀系统时,会遇到一些挑战

1、巨大的瞬时流量:秒杀活动会在同一时刻吸引大量用户,瞬间的高并发流量会给系统带来巨大压力。如果处理不好,系统会瘫痪。
2、热点数据问题:高并发下,抢购同一个商品会导致存储系统的热点问题,尤其是商品库存的控制。
3、刷子流量:很多秒杀活动是通过HTTP服务提供的,刷子可以通过程序频繁发送请求,占用正常用户的抢购通道,增加系统负担。

秒杀系统设计

在设计秒杀系统之前,我们先了解一下用户的HTTP请求是怎么走的

1、DNS:这是负责把域名解析成实际IP地址的地方。浏览器会缓存这个IP,下次再访问时直接用这个IP建立连接。
2、Nginx:这个负责接收客户端请求,然后根据负载均衡算法(比如轮询)把请求分发给下游的Web服务。它还能做静态资源服务器。
3、Web服务:这是我们写业务逻辑的地方,比如处理用户请求、提供页面数据等。
4、RPC服务:这些是支撑业务的基础服务,一般只供内部调用,不对外开放。

了解了请求的链路后,我们再看看用户在秒杀过程中要做什么

支付部分,对于一般平台来说,都是通用板块,而显示商详页部分(头部机 构,可能这个部分也属于通用板块)和从“点击抢购”开始到“下单成功待支付”, 这一段都是属于秒杀系统的业务范畴,

在这里我们梳理下,有哪几件事情是和秒杀相关的

  1. 秒杀的活动数据:展示倒计时、活动开始、结束等信息,用户通过这些信息进入抢购入口。

image.png 2. 提供结算页:展示商品的抢购信息,如名称、价格、数量、地址、支付方式等。

  1. 提供下单服务:用户提交订单后,生成订单或将下单数据传递给下游服务。

插播一条:如果你近期准备面试跳槽,建议在cxykk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题、简历模板、算法刷题。

秒杀系统的架构设计

一般大网站在DNS层会做一些防攻击措施,这层和我们没啥关系。

接着是Nginx层。 Nginx不仅能做反向代理和负载均衡,还能做静态资源服务器。如果我们把业务校验也放在这里,就能实现校验前置。

然后是Web服务层,负责业务聚合、提供结算页数据和控制流量,保证下游系统的安全。

最后是RPC服务层,提供基础服务,经过前面几层筛选,到这儿的请求已经少很多了。

通用的秒杀系统架构

看一下常见的秒杀系统架构图:

这种功能结构以及系统架构,是我们非常熟悉的。

很多时候,Nginx 只做反向代理和负载均衡,甚至这层对大部分做业务开发的研发人员来说,都是无感知的,一般运维部门在做生产环境搭建时,都会配好。

研发人员更多的是在开发Web 服务和其他 RPC 服务/微服务,我们把页面以及页面所依赖的静态资源都放到 Web 服务中,同时 Web 服务还提供业务接口,RPC 服务提供一些支撑服务。

当然,像电商商城进行动静分离后,VUE 前端部分也会放在 Nginx 上,这就变成了页面以及页面所依赖的静态资源也在 Nginx 上,Web 服务提供业务接口,这种模式相比上面的有所改进。

但是对于秒杀来说瞬时流量非常大的情况,就会有很多问题:

问题1:页面访问

商城虽然进行了动静分离,商详页实现在 product.vue 中。但是,每个商品都会去后端获得商品的详细信息并展示。

mounted() {
    window.scroll(x: 0, y: 0);
    this.getProductInfo();
},
methods: {
    getProductInfo() {
        let id = this.$route.params.id;

        this.axios.get(`/pms/productInfo/${id}`).then((res) => {
            this.product = res;
        });
    }
}

可以想到,这种实现的商详页在秒杀高并发的情况下,不做任何措施,会对后端服务,特别是产品服务和数据库造成非常大的访问压力,即使产品信息全部缓存,依然会消耗大量的后端资源和带宽。

问题2:Web服务器性能问题

一般部署 Web 服务,都是使用 Tomcat 来部署的, Tomcat 在处理请求的时候,是通过线程去处理的。

这样的问题就是如果瞬时的大量请求过来,线程池中的线程不够用,Tomcat就会瞬间新建很多线程,直至达到配置的最大线程数,如果线程数设置的过大,这个过程可能会直接将机器的 CPU 打满,导致机器死掉。

即使没有挂掉,在高负载下,当设置的等待队列也满了之后,后面的请求都会被拒绝连接,直到有空出的资源去处理新请求。

这时候你可能会想,我加机器分摊流量不就行了?
可以是可以,但由此增加的活动成本有可能超出预算。

除此之外,还会伴有类似读写热点、库存超卖等等问题

插播一条:如果你近期准备面试跳槽,建议在cxykk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题、简历模板、算法刷题。

大厂高并发秒杀系统架构设计

看到这张图,很多同学可能会有疑惑?

看起来似乎和一般的系统架构没什么区别

其实仔细研究,区别还是很大的。

  1. 下原先由Web 服务或Nginx服务提供的静态资源放到了CDN

CDN是全国都有的服务器,客户端可以根据所处位置自动就近从 CDN 上拉取静态资源,速度更快),来大大减轻抢购瞬时秒杀域名的负担

  1. 将 Nginx 的职责放大,前置用来做 Web 网关,承担部分业务逻辑校验,并且可能增加黑白名单、限流和流控的功能

这种在 Nginx 里写业务的做法在很多大公司里都是很常见的,像京东是用来做商详、秒杀的业务网关,美团用来做负载均衡接入层,12306 用来做车票查询等等

为什么要这么做呢?

这么做的目的,就是要充分利用 Nginx 的高并发、高吞吐能力,并且非常契合秒杀业务的特点:

即入口流量大,但流量组成却非常的混杂,这些请求中,一部分是刷子请求,一部分是无效请求(传参等异常),剩下的才是正常请求。

一般情况下这个的比例可能是 6:1: 3,所以需要在网关层尽可能多地接收流量进来,并做精确地筛选,将真正有效的 3 成请求分发到下游,剩余的 7 成拦截在网关层。不然把这些流量都打到 Web 服务层,Web 服务再新起线程来处理刷子和无效请求,这是种资源的浪费。

所以网关层对秒杀系统而言,至关重要,而 Nginx 刚好可以胜任此项任务。 所以 Nginx 在主要的秒杀系统设计中,扮演着非常重要的角色

商城/秒杀系统设计和实现

那具体的商城/秒杀系统该如何设计呢? 请看下面的系统数据流转部署架构图

秒杀业务流程梳理

根据我们之前对秒杀业务的介绍,一场完整的秒杀活动大概是这样的流程

我们可以结合上面的架构图来梳理一下:

  1. 创建秒杀活动:运营人员在秒杀系统的后台,选择指定的商品,创建秒杀活动,设置开始时间、结束时间和活动库存等信息。

  2. 活动启动:在活动开始之前,运营后台会启动秒杀活动,同时将秒杀活动信息写入商城系统的 Redis 集群,并将商品库存等信息写入秒杀系统的 Redis 主从集群。

  3. 用户准备秒杀:用户进入秒杀商品详情页,准备参与秒杀。

  4. 点击抢购按钮:在详情页上,用户可以看到“立即抢购”的按钮。这里可以通过增加一些逻辑判断来限制按钮是否可以点击,比如用户等级、活动库存是否足够、是否需要预约等。如果没有限制,用户可以点击抢购按钮,进入秒杀结算页。

  5. 结算页面:在结算页,用户可以更改购买数量,切换地址、支付方式等。结算页的元素会根据实际业务需求定制,更复杂的场景下,还可以支持积分、优惠券、红包、配送时效等,这些都会影响最终价格的计算。

  6. 提交订单:确认无误后,用户提交订单。此时,后台服务会调用风控和限购等接口进行校验,所有校验通过后,完成库存的扣减和订单的生成。

  7. 支付跳转:订单完成后,根据用户选择的支付方式跳转到相应页面,比如在线支付跳转到收银台,货到付款则跳转到下单成功提示页。

这样一来,从秒杀活动的启动到用户抢购成功,直到活动结束,整个流程就形成了一个闭环。

当然,上述只是主要流程,实际业务中可以根据需求在不同节点添加功能,灵活调整。我们这里只列举了主要要素。

秒杀系统设计

设计1:秒杀的隔离

为了不让 0.001%的爆品影响 99.999%普通商品的交易,我们很快就想到了隔离。

隔离是控制危险范围的最直接的手段,

面对超预期的瞬时流量,我们也要采取很多措施进行流量的隔离,防止秒 杀流量串访到普通商品交易流程上,带来不可预估的灾难性后果

1、业务隔离

秒杀商品的稀缺性,决定了它们不会像普通商品那样进行售卖。

一般会有计划地进行营销策划,制定详细的方案,以达到预期目标。

因此,从业务角度看,秒杀商品的售卖流程和普通商品完全不同,它需要一个提报过程。

大部分电商平台会有一个专门的提报系统(我们系统中没有实现这部分)。

商家或业务人员可以根据自己的运营计划,在提报系统里进行活动提报,提供参与秒杀的商品编号、活动起止时间、库存量、限购规则、风控规则,以及参与活动群体的地域分布、预计人数、会员级别等基本信息。

对于大平台来说,提报过程和这些基本信息非常重要。

有了这些信息作为输入,技术部门可以预估出大致的流量、并发数等,并结合系统当前的容量情况,评估是否需要扩容、降级或调整限流策略。

因此,业务隔离的重要性也很高。

2、系统隔离

接下来我们谈谈系统隔离。

之前我们提到过商品交易流程涉及到哪些系统,理论上讲,应该把交易链路上的所有系统单独复制部署一套,彻底隔离。

但这样做成本太高,大部分电商平台都采用分布式微服务架构,服务数量少则几十个,多则几百个,全都复制一套不现实。

所以比较常见的做法是对核心系统进行物理隔离,而对于链路末端的一些系统,因为前面已经进行了流量削峰,流量变得可控,这些系统可以不做物理隔离。

用户秒杀时一定是先进入商品详情页(很多电商的秒杀系统会在详情页进行倒计时,时间到了才能点击秒杀按钮进行抢购)。所以第一个需要关注的系统就是商品详情页,我们需要申请独立的秒杀详情页域名、独立的 Nginx 负载均衡器,以及独立的详情页后端服务。

如果可能,还需要对域名进行隔离,申请一个独立的域名,专门用来承接秒杀流量,流量从专有域名进来后,分配到专有的负载均衡器,再路由到专门的微服务分组,这样就做到了从入口到微服务的流量隔离。

一般来说,秒杀中流量冲击比较大的核心系统就是秒杀详情页秒杀结算页秒杀下单库存扣减,这些是我们重点关注的对象。

相对链路末端的一些系统,经过前面的削峰后,流量变得可控,比如收银台、支付系统,物理隔离的意义不大,反而会增加成本。

3、数据隔离

现在,我们已经完成了应用层的隔离。

接下来,在数据层面,我们也应该进行相应的隔离,否则如果共用缓存或者共用数据库,—旦瞬时流量把它们冲垮,照样会影响普通商品的交易。

数据层的专有部署,需要结合秒杀的场景来设计部署拓扑结构,比如 Redis 缓存,一般的场景一主一从就够了,但是在秒杀场景,需要一主多从来扛读热点 数据。

通过上面3个方面的隔离考虑,实际部署架构如下

可以看到在我们的商城系统中,秒杀服务从 Nginx 服务到后面的秒杀确认单处理服务秒杀订单处理服务都是独立部署的,而且秒杀系统拥有自己独立的 Redis 主从集群。

插播一条:如果你近期准备面试跳槽,建议在cxykk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题、简历模板、算法刷题。

秒杀系统设计具体实现

从首页点击秒杀栏商品首先跳转到的就是商详页,这个页面的展示由秒杀系统的第一站 Nginx 负责的,所以我们先来看看它。

1、Nginx层优化

前面我们说过,Nginx 在主要的秒杀系统设计中,扮演着非常重要的角色,意味着 Nginx 上要承载很多的业务逻辑。Nginx 的底层模块一般都是用 C 语言写的,如果我们想在 Nginx 的基础之上写业务逻辑会很不方便,所以这个时候我们还得借助 OpenResty,它是 Nginx 的一个社区分支。

什么是OpenResty?

OpenResty 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。 这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统

商城秒杀系统中的OpenResty

秒杀的 OpenResty 就不仅仅承担着反向代理和负载均衡的职能,例如:

还承担着网关、静态模板化网页访问、静态资源访问、流量管控、防刷等一系列职能。 例如:

这些都需要我们使用 Lua 脚本来完成,配置一下对 Lua 脚本的支持

2、商详页静态化

前面说过商城进行了动静分离,商详页实现在 product.vue 中,每个商品都 会去后端获得商品的详细信息并展示。在秒杀高并发的情况下,不做任何措施, 会对后端服务造成非常大的访问压力。

仔细想一下,我们知道,进行秒杀的商品是确定的,和秒杀商品相关的属性,

比如规格、图片地址等都是确定的

在用户进入秒杀商详页时并不需要每次都从后端服务获取,在商城秒杀项目中,唯一需要每次获取的只有商品的当前秒杀库存。

那么我们为什么不把秒杀的商品详情页静态化呢?

这样可以充分利用 Nginx对静态网页的高性能处理能力

3、商详页的库存获取

用户访问秒杀的商详页,我们用静态网页展示给了用户,但是有些数据还是需要动态获取的。

比如秒杀商品的库存。

虽然库存在生成静态网页时已经初始化为商品的活动预设库存数

但是随着活的的进行,这个库存数肯定会发生变化,我们当然希望尽可能的 及时反应库存的变化。
从前面的秒杀架构图我们已经知道秒杀系统的 Redis 主从集群会有秒杀商品 库存的信。

很明显,按照我们一般的做法,访问路径应该是这样的

但是仔细想想,有必要吗?后端服务在这里只是起了一个转发的作用,为什 么我们不直接让 Nginx 访问 Redis 来获得商品的当前库存呢?

这样的话,既降低了后端服务的压力,又提升了秒杀系统的性能。

所以在 OpenResty 中查询库存的时候,我们可以直接访问Redis。

4、流量管控

4.1 前期流量管控

为什么要前期流量管控?

通过对秒杀流量的隔离,我们已经能把瞬时的大流量控制在隔离的秒杀环境里了。

接下来,我们要考虑隔离环境的高可用问题。

通俗点说,就是在保障普通商品交易流程的基础上,确保秒杀系统在流量冲击下也能稳定运行。

方法有很多,包括流量控制、削峰、限流、缓存热点处理、扩容、熔断等措施。

首先来看流量控制

在库存有限的情况下,过多的用户参与实际上对电商平台的价值是递减的。

举个例子,假设有 1 万台手机,如果 100 万用户和 1000 万用户同时来抢,对电商平台的经济效益和社会影响并不会有 10 倍的差距。反而,用户越多,一方面消耗更多的机器资源,另一方面,抢不到商品的用户越多,电商平台面临的投诉和舆论压力也越大。
当然,如果想让所有用户都能参与秒杀,系统可以通过扩容来实现,但成本太高,ROI 不划算,所以需要提前对流量进行管控。

很多电商平台,特别是大型电商,常常采用“预约+秒杀”的方式进行营销。

  1. 在预约期内,开放用户预约,获取秒杀资格;

  2. 在秒杀期内,只有具备抢购资格的用户才能参与秒杀。

  3. 在预约期内,关键是锁定用户,这也是做前期流量管控的核心。

插播一条:如果你近期准备面试跳槽,建议在cxykk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题、简历模板、算法刷题。

4.2 秒杀中的流量管控

4.2.1 削峰

我们已经知道了秒杀有隔离和事前流量控制,其目的是降低流量的相互耦合和量级,减少对系统的冲击。秒杀系统事中流量管控——削峰和限流让系统更加稳健。

真实场景下的秒杀流量一般几秒内爬升到峰值,然后很快往平常值回归。

我们现在需要做的就是通过削峰和限流,把这超大的瞬时流量平稳地承接下来,落到秒杀系统里。

削峰的方法有很多,可以分为无损有损削峰。

本质上,限流是一种有损削峰;
而引入验证码、问答题以及异步化消息队列可以归为无损削峰

无损削峰

互联网常用的削峰手段有哪些呢?

1、验证码和问问题

在秒杀交易流程中,引入验证码和问答题,有两个目的:

  • 一是快速拦截掉部分刷子流量,防止机器作弊,起到防刷的作用;
  • 二是平滑秒杀的毛刺请求,延缓并发,对流量进行削峰。

让用户在秒杀前输入验证码或者做问答题,不同用户的手速有快有慢,这就起到了让 1s 的瞬时流量平均到 30s 甚至 1 分钟的平滑流量中,这样就不需要堆积过多的机器应对 1s 的瞬时流量了。

2、消息队列

除了验证码和问答题,另—种削峰方式是异步消息队列。

当服务 A 依赖服务 B 时,正常情况下服务 A 会直接通过 RPC 调用服务 B 的接口,当服务 A 调用的流量可控,且服务 B 的 TP99 和 QPS 能满足调用时,这是最简单直接的调用方式,没什么问题,目前大部分的微服务间调用也都是这样做的。

但是,试想一下,如果服务 A 的流量非常高(假设 10 万 QPS),远远大于服务B 所能支持的能力(假设 1 万 QPS),那么服务 B 的 CPU 很快就会升高,TP99 也随之变高,最终服务 B 被服务 A 的流量冲垮。

这个时候,消息队列就派上用场了,我们把一步调用的直接紧耦合方式,通过消息队列改造成两步异步调用,让超过服务 B 范围的流量,暂存在消息队列里,由 B 根据自己的服务能力来决定处理快慢,这就是通过消息队列进行调用解耦的常见手段

常见的开源消息队列有 Kafka、RocketMQ 和 RabbitMQ 等

有损削峰
限流

对于秒杀流程来说,从用户开始参与秒杀,到秒杀成功支付完成,实际上经 历了很多的系统链路调用,中间有非常庞杂的系统在支撑,比如有商详、风控、 登录、限购、购物车以及订单等很多交易系统。

所以主流的做法是从上游开始,对流量进行逐级限流,分层过滤,优质的有效的流量最 终才能参与下单。

1、Nginx限流

Nginx 本身也提供了非常强大的限流功能,比如有两个专门的限流模块 HttpLimitzone 和 HttpLimitReqest,HttpLimitzone 用来限制一个客户端的并发连接 数,HttpLimitReqest 通过漏桶算法来限制用户的连接频率。

2、应用/服务层限流

应用层的限流手段也是比较多的,比如说线程池和 API 限流的方法。

线程池限流

Java 原生的线程池原理相信你非常清楚,我们可以通过自定义线程池,配置 最大连接数,以请求处理队列长度以及拒绝策略等参数来达到限流的目的。

当处理队列满,而且最大线程都在处理时,多余的请求就会被拒绝策略丢弃,也就是 被限流了。

API 限流

线程池限流可以看做是一种并发数限流,对于并发数限流来说, 实际上服务提供的 QPS 能力是和后端处理的响应时长有关系的,在并发数恒定 的情况下,TP99 越低,QPS 就越高。

然而大部分情况是,我们希望根据 QPS 多少来进行限流。

这时候就可以引入Sentinel,可以从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助保障微服务的稳定性。

总结

大厂秒杀系统是一个超高并发的抢购系统,最大的技术挑战是瞬时流量非常大,在分析了业界常规秒杀系统解决方案的基础上,我们采用了新的秒杀架构设计方案:

  1. 业务隔离
  2. 应用隔离
  3. 数据隔离

并且在具体实现上,又做了商详页静态化、商品库存查询链路优化、流量分层过滤、逐级限流等手段,来保障系统的稳定性和高可用。

由于篇幅有限,其实秒杀系统还有很多问题,比如库存的原子扣减、秒杀数据的写/读热点、防刷、风控、容灾等设计,都最终影响秒杀系统的稳定性和高可用。

感兴趣的小伙伴可以在评论区留下“想看”的留言,如果人数够多,我就考虑继续写一篇文章,说一下秒杀系统剩下需要解决的问题(库存的原子扣减、秒杀数据的写/读热点、防刷、风控、容灾)

最后说一句(求关注,求赞,别白嫖我)

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。 这是大佬写的, 7701页的BAT大佬写的刷题笔记,让我offer拿到手软

本文,已收录于,我的技术网站 cxykk.com:程序员编程资料站,有大厂完整面经,工作技术,架构师成长之路,等经验分享

求一键三连:点赞、分享、收藏

点赞对我真的非常重要!在线求赞,加个关注我会非常感激!