本文原文链接
尼恩说在前面
在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,
最近有小伙伴面试招商银行,遇到下面的绝命 12题,狠狠被拷打了, 彻底懵了。 项目场景题太难了,不好好准备,真的答不出!
所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
当然,这些面试题 以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V171版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
绝命12题, 尼恩将给出全部的深度答案:
1.如何让系统抗住大促的预约抢购活动?
2.如何从零搭建10万级QPS大流量、高并发优惠券系统?
3.百万级别数据的 Excel 如何快速导入到数据?
4.如何设计一个支持万亿GB网盘实现秒传与限速的系统?
5.如何根据应用场景选择合适的消息中间件?
即将发布。
6.如何提升 RocketMQ 顺序消费性能?
即将发布。
7.使用分布式调度框架该考虑哪些问题?
即将发布。
9.如何让系统抗住大促的预约抢购活动?
本文。
10.问 : 如何解决高并发下的库存抢购超卖少买?
即将发布。
11.为什么高并发下数据写入不推荐关系数据?
即将发布。
12.如果让你设计一个分布式链路跟踪系统?
即将发布。
本文目录
一:预约抢购” 的三个阶段 :
在大促活动期间,“预约抢购” 是各大 电商平台 的主要促销手段, 比如 2019 年的 “1499 元抢购飞天茅台”活动,
那么,如何才能让系统抗住大促的预约抢购活动?
或者,如何才能 让系统抗住双十一的预约抢购活动?
尼恩给大家系统化、体系化的梳理一下。
我们先把需求梳理一下,总的来说,实现一个抢购系统大概可以分为3个阶段。
整体功能 分为 “抢购预告”、“抢购下单” 和 “订单支付” 三个阶段、三个功能,代表用户在双十一大促抢购活动中的不同阶段。
抢购预告阶段
目的在于吸引用户关注、激发用户参与抢购的兴趣,让用户提前做好准备。
主要是提前向用户展示即将开展抢购活动的相关信息,像参与抢购的商品品类、各商品的大致优惠幅度、具体的抢购开始时间等内容。
商品抢购阶段
对于抢购详情页面,临近抢购倒计时,页面查询请求剧增。为应对这一情况,采取页面静态化和服务端限流措施。页面静态化使页面能快速加载,减少动态请求压力;服务端限流则控制单位时间内请求数量,防止流量过大导致系统崩溃。
对于抢购下单,由于瞬时下单操作对DB带来巨大压力,需要通过 MQ(消息队列)将同步转异步,实现流量削峰。这使得请求排队等待,有序且有限地进入后端服务。同时,要解决消息队列的丢失、重复和积压问题。扣减库存时,引入锁机制,防止扣减存储超售,和保障操作的幂等性。 通过本地消息表事务,保障秒杀订单服务/ 库存服务/积分服务/优惠券服务的最终一致性。
订单支付阶段
用户支付完成后,通过 MQ 通知方式实现系统间解耦和异步通信。确保消息可靠性,也可通过 RPC(远程过程调用)同步调用方式。掌握 RPC 和 MQ 的相关知识点,保证支付完成后系统的稳定运行。
二: 预告阶段的架构设计
抢购的预告阶段,目的在于吸引用户关注、激发用户参与抢购的兴趣,让用户提前做好准备。
抢购的预告阶段,主要是提前向用户展示即将开展抢购活动的相关信息,像参与抢购的商品品类、各商品的大致优惠幅度、具体的抢购开始时间等内容。
抢购的预告阶段,采用分层架构来应对高并发的抢购预告请求。
抢购预告 阶段 是4层,主要分为:
- 接入层
- 业务逻辑层
- 缓存层
- 数据存储层
抢购预告阶段 的 接入层、业务逻辑层、数据存储层以及缓存层,各层协同工作确保系统能够高效、稳定地处理大量并发请求并准确展示抢购预告信息。
(1)抢购预告接入层
负载均衡:
使用专业的负载均衡设备(如硬件负载均衡器 F5 或者软件负载均衡器 Nginx 等),按照一定的算法(如轮询、IP 哈希等)将大量用户的请求均匀分发到后端的多个业务服务器上,避免单点服务器出现过载的情况,有效提升系统整体的并发处理能力。
请求过滤与验证:
对传入的请求进行合法性检查,比如验证请求的来源 IP 是否在允许范围内、请求格式是否符合规范等,拦截非法请求,减轻后续业务逻辑层的处理压力。
(2)抢购预告业务逻辑层
信息整合与组装:
从缓存层获取商品相关的基础信息(如商品品类、大致优惠幅度等)以及从数据库获取最新的动态信息(如临时调整的优惠规则等),将这些信息进行整合组装,形成完整的抢购预告内容。
消息队列应用:
如果存在需要实时推送的信息更新(如优惠力度变化等情况),借助消息队列(如 RabbitMQ、Kafka 等)来实现异步通知,业务逻辑层将更新消息发送到消息队列中,由专门的消费者去处理更新并推送到前端展示,确保数据实时性的同时不会阻塞主要的请求处理流程。
(3)抢购预告缓存层
静态资源缓存:
采用动静分离策略,将商品图片、固定的文案描述等静态资源缓存到 CDN(内容分发网络)中。
CDN 在全球各地有众多节点,当不同地区用户发起请求时,能从距离最近的节点快速获取这些静态资源,大大缩短资源获取时间,减轻后端服务器压力。
动态数据缓存(部分):
在抢购预告中,对于一些相对变动不那么频繁的商品动态数据(如短期内不会改变的商品品类列表等),可以缓存到内存数据库(如 Redis)中。
通过 Cache Aside 模式进行redis 和db的访问 ,在业务逻辑层查询时先从 Redis 中获取 动态数据,若不存在, 再去数据库查询。
如何保障 数据一致性呢? 通过设置合理的缓存过期时间和更新机制,保证数据的时效性和准确性。
以 抢购预告的类目列表为例,流程如下:
三:预告阶段的架构难点:
难点1:页面优化与缓存策略:
面对大量用户同时访问预告页面的情况,需对页面进行性能优化。
采用动静分离的方式,将商品图片、固定的文案描述等静态资源通过 CDN(内容分发网络)进行缓存,这样能让不同地区的用户快速获取到这些资源,减轻后端服务器的压力,保障页面能在高并发访问下快速加载呈现。
难点2:数据实时更新与一致性保障:
对于商品信息、优惠规则等动态数据,要确保其能实时准确地展示给用户。
后端数据库的数据变更(比如临时调整优惠力度等)需要及时同步到前端,可通过消息队列等机制来实现数据的异步更新推送,避免出现用户看到的预告内容与实际抢购情况不符的问题。
难点3:流量监控与预警:
搭建完善的流量监控系统,实时监测访问该阶段页面的流量情况,设定合理的阈值,
当流量接近或超过系统承载能力时能够及时发出预警,以便运维团队提前做好应对准备,比如动态增加服务器资源等。
四:抢购下单阶段的架构设计
下单业务特点与目标:
这是整个抢购活动最为关键且高并发压力最大的阶段,众多用户会在同一时间点尝试下单 ,这里存在巨大的顺时流量、突发流量。
顺时流量、突发流量 场景,在涉及高并发难题的同时,还要做到到对库存的准确扣减、订单生成的合法合规的等重要业务操作。
下单阶段 需要确保整个下单流程快速,且不出差错,以提升用户的抢购体验和保障商家利益。
抢购下单阶段的4层架构
抢购的下单阶段,同样 采用分层架构来应对高并发 请求进行处理。
抢购下单阶段也是4层,主要分为:
接入层
业务逻辑层
MQ层
数据存储层
其中业务逻辑层解耦为:
- 库存预扣服务
- 订单生成服务
各层协同工作确保系统能够高效、稳定地处理大量并发请求并准确完成下单操作。
(1) 库存预扣服务 架构设计:
采用分布式缓存(如 Redis 等)来预先存储商品库存,在用户下单时先从缓存层进行库存预扣减操作,这个环节,利用缓存的高性能读写特性加快响应速度。
同时,要结合数据库的持久化存储,通过异步MQ层 将缓存中的库存变动同步到数据库中,确保数据最终一致性。
(2) 订单生成服务 的架构设计:
设计高效的订单生成逻辑,快速生成唯一且符合规范的订单号,将商品信息、订单信息等关键数据准确无误地写入数据库中的订单表。
订单生成过程中,运用合适的锁机制(如分布式锁、乐观锁等),有效避免超卖情况发生,保证同一商品在同一时刻只有一个有效的库存扣减操作在执行。
可以借助数据库连接池技术来管理数据库连接,提高订单写入的效率,减少因频繁创建和销毁数据库连接导致的性能损耗。
(3) 高并发抢购下单的核心策略:
第一: 限流设计
设置合理的限流策略,例如基于令牌桶算法、漏桶算法等方式,限制单位时间内进入下单流程的请求数量,对超出限制的请求可以进行排队等待或者友好提示用户稍后再试。
第二:降级设计
同时,制定降级方案,当一些非核心服务(如商品关联推荐服务等)出现故障或者性能瓶颈时,能够暂时关闭这些服务,优先保障下单这一核心功能的稳定运行,避免整个系统因局部问题而崩溃。
五:订单支付阶段
业务特点与目标:
用户完成下单后进入支付环节,支付环节 需要很多安全保障:
- 第一,需要保障支付过程的安全、稳定以及与各支付渠道(如支付宝、微信支付等)的顺畅对接。
- 第二,需要准确更新订单的支付状态,确保整个交易流程的完整性,让用户放心完成支付。
订单支付阶段的大致流程:
用户完成下单后进入支付环节,调用 支付平台 的接口,发起支付流程
在用户支付订单完成之后,一般会由支付平台回调系统接口,更新订单状态。
在支付回调成功之后,抢购系统还会通过异步通知的方式,实现订单更新之外的非核心业务处理,比如积分累计、短信通知等,此阶段可以基于 MQ 实现业务的异步操作。
5.1 订单支付后设计
不过针对服务的异常(如宕机),会存在 MQ消息数据丢失的可能,
比如当支付回调系统后,修改订单状态成功了,但是, 在异步通知积分系统, MQ消息数据丢失 ,其他的业务就没有 处理了,出现了数据不一致性问题。
5.2 订单支付后操作(异常)
所以你还要考虑 可靠消息投递机制:先做消息的本地存储,再通过异步重试机制,来实现消息的补偿。
比如当支付平台回调订单系统,然后在更新状态的同时,插入一个消息,之后再返回第三方支付操作成功的结果。
最后,通过数据库中的这条消息,再通过XXL-JOB 订单核对方式机制,完成后续的工作。
另外,也可以采用消息的0丢失机制,保障消息不丢失。消息的0丢失机制, 具体请参见下面的文章:
5.3:异常处理与补偿机制:
针对支付过程中可能出现的各种异常情况,比如网络波动导致支付结果未及时返回、用户主动取消支付等,需要建立完善的异常处理和补偿机制。
例如,设置xxl-job 定时任务定期查询处于未确定支付状态的订单情况,提供给用户相应的操作入口(如重新支付、取消订单等),保障用户能顺利完成支付或者妥善处理异常订单,维护好用户体验和整个交易流程的顺畅性。
5.4 支付阶段技术设计难点
难点1:支付接口集成与安全保障:
与各类支付平台进行严谨的接口对接,按照支付平台要求做好接口参数的传递、加密、签名等安全措施,防止支付信息在传输过程中被篡改。
需要对支付接口进行充分的测试,确保其在高并发环境下的稳定性和可靠性,能够及时准确地向支付平台发起支付请求并接收支付结果回调。
难点2:订单状态更新与事务管理:
依据支付结果来精准更新订单的状态,如支付成功后将订单标记为 “已支付”,支付失败则相应标记为 “支付失败” 等。
这一过程要保证在高并发情况下状态更新的一致性,可借助数据库事务机制或者可靠的消息队列来实现,需确保支付成功后,与之关联的库存、财务等相关数据也能同步正确更新,避免出现数据不一致导致的后续业务问题。
说在最后:有问题找老架构取经
回到开始的时候的面试题:招商银行的Java后端面试真题
被狠狠拷打了,问的人都懵了。 项目场景题太难了,不好好准备,真的答不出!
按照尼恩的参考答案回答,一定会 吊打面试官,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。
在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。
很多小伙伴刷完后, 吊打面试官, 大厂横着走。
在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。
另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。前段时间,刚刚指导 一个2年经验小伙,拿到 年薪60W的 天价年薪 ,3大 offer, 实现了一本 吊打 985、211。
狠狠卷,实现 “offer自由” 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 “offer自由” 。
尼恩技术圣经系列PDF
- 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
- 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
- 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
- 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
- 《大数据HBase学习圣经:一本书实现HBase学习自由》
- 《大数据Flink学习圣经:一本书实现大数据Flink自由》
- 《响应式圣经:10W字,实现Spring响应式编程自由》
- 《Go学习圣经:Go语言实现高并发CRUD业务开发》
……完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓