文章目录
- 资料
- 项目经历
- 技能清单
- 自我介绍
-
-
- QPS和TPS?
- 如何设计一个排行榜的功能?
- 如何解决大文件上传问题
- 延时任务处理场景
- 如何设计一个秒杀系统?
- 分布式幂等性如何设计?
- 如果你的系统的QPS 突然提升10倍你会怎么设计?
- 如何从零搭建 10 万级QPS 大流量、高并发优惠券系统?
- 高 QPS,高并发的场景下可能会出现redis超时,请问如何解决?
- 如何设计 RPC 框架在10 万QPS下实现毫秒级的服务调用?
- 在你上一家公司中是如何如何实现蓝绿发布的?
- 使用分布式调度框架该考虑哪些问题?
- OOM、CPU预警、内存预警之类的问题如何排查?
-
-
- 第一步,通过业务⽇志分析排查
- 第二步,可以通过APM 分析排查
- 第三步,物理环境排查
- 第四步,使用arthas工具
- 第五步,使用JVM 问题定位命令
- 第六步,内存分析工具 MAT
-
- 线上的 API 接口响应比较慢,该如何快速排查和定位问题?
- 所有接口响应慢,如何排查
- MySQL 数据库cpu 飙升的话,要怎么处理呢?
- 百万级别数据的Excel 如何快速导入到数据库中?
- 如果JVM出现频繁FullGC该如何解决
- JVMOOM问题如何排查和解决?
- java.lang.OutOfMemoryError: Java heap space堆内存溢出问题如何排查和解决?
- 数据库出现死锁如何排查?
- 聊聊你印象最深刻的项目,或者做了什么优化
- 聊聊项目,好的设计,好的代码
-
资料
https://doocs.github.io/advanced-java/#/?id=%e4%ba%92%e8%81%94%e7%bd%91-java-%e5%b7%a5%e7%a8%8b%e5%b8%88%e8%bf%9b%e9%98%b6%e7%9f%a5%e8%af%86%e5%ae%8c%e5%85%a8%e6%89%ab%e7%9b%b2
《2024年更新Java面试指南(配套Java面试突击-V5.0)》的以下内容:
系统设计题
项目经历
技能清单
自我介绍
有比较丰富的redis使用场景,还有就是之前项目上面强依赖于netty,所以我也研究过netty的源码
QPS和TPS?
什么是QPS?
Queries Per Second,意思是每秒查询率。就是每秒的查询数,对数据库而言就是数据库每秒执行的 sql 数( insert、select、update、delete 等)
如下图:系统服务器向MySql服务器发送了一条sql,对于MySQL服务器来说,QPS为1(一秒内)
TPS:
tps(transactions per second)每秒事务数。以 commit 成功次数为准。
如下图,系统服务器中的一个请求处理向Mysql发送了2条insert和1条update,并成功执行了commit(1秒内),则对于MySQL服务器来说,TPS为1,QPS为3。
如何设计一个排行榜的功能?
①MySQL 的 ORDER BY 关键字
SELECT column1, column2, ...
FROM table_name
ORDER BY column1, column2, ... ASC/DESC;
②Redis 的 sorted set
如果说你的项目需要排序数据量比较小并且业务场景不复杂的话,直接使用 MySQL 的ORDER BY 关键字就可以了,没必要为了排行榜引入一个 Redis。
如何解决大文件上传问题
试想一个,你想上传一个 5g 的视频,上传进度到 99% 的时候,特么的,突然网络断了,这个时候,你
发现自己竟然需要重新上传。我就问你抓狂不?
有没有解决办法呢? 答案就是:分片上传!只需要先将文件切分成多个文件分片,然后再上传这些小的文件分片。前端发送了所有文件分片之后,服务端再将这些文件分片进行合并即可。使用分片上传主要有下面 2 点好处:
- 断点续传 :上传文件中途暂停或失败(比如遇到网络问题)之后,不需要重新上传,只需要上传那
些未成功上传的文件分片即可。所以,分片上传是断点续传的基础。 - 多线程上传 :我们可以通过多线程同时对一个文件的多个文件分片进行上传,这样的话就大大加快
的文件上传的速度。
延时任务处理场景
日常开发中,我们经常遇到这种延时任务处理场景,如:
- 外卖订单超 30 分钟未支付,则自动取订单;
- 用户注册成功 15 分钟后,发短信息通知用户等等。
- 到期自动收货
- 超时自动退款
在电商,支付等系统中,一设都是先创建订单(支付单),再给用户一定的时间进行支付,如果没有按时支付的话,就需要把之前的订单(支付单)取消掉。如何实现这种自动关单的需求?
①通过定时任务关闭订单:写一个定时任务定期扫描数据库中的订单。
不推荐,由于定时任务扫描的间隔是固定的,所以可能造成一些订单已经过期了一段时间才被扫描到,订单关闭的时间比正常时间晚一些。
②延时队列:
- 在rabbitmq中不存在延时队列,rabbitmq都是通过设置消息的过期时间和死信队列来模拟出延时队列。
- JDK 延迟队列 DelayQueue。这种方式不依赖任何第三方组件,是JDK自带的,但是由于DelayQueue 基于 JVM 内存,如果 JVM 重启了,那所有数据就丢失了。而且如果放入的数据过多,会造成JVMOOM。所以它只适合数据量较小,且丢失也不影响主业务的场景,比如内部系统的一些非重要通知,就算丢失,也不会有太大影响。
- RocketMQ 的延迟队列。RocketMQ是支持延时队列的。在订单创建之后,我们就可以把订单作为一条消息投递到 rocketmq,并将延迟时间设置为 30 分钟,这样,30 分钟后我们定义的 consumer 就可以消费到这条消息,然后检查用户是否支付了这个订单。
③RabbitMQ 死信队列
谷粒商城里面的场景
除了 RocketMQ 的延迟队列,RabbitMQ 的死信队列也可以实现消息延迟功能。当 RabbitMQ 中的一条正常消息,因为过了存活时间(TTL 过期)、队列长度超限、被消费者拒绝等原因无法被消费时,就会被当成一条死信消息,投递到死信队列。基于这样的机制,我们可以给消息设置一个 ttl,然后故意不消费消息,等消息过期就会进入死信队列,我们再消费死信队列即可
如何设计一个秒杀系统?
以极低的价格,让大量的用户参与,进而造成系统在极短的时间内有极高的流量。因此其稳定性、高可用是我们考虑的第一位。
前端优化:
- 动静分离
- 请求频率限制:我们可以在用户发起秒杀请求之前让其进行答题或者输入验证码。这种方式一方面可以避免用户请求过于集中,另一方面可以有效解决用户使用脚本作弊。
后端优化
- 增加缓存层 + 预热数据
- MQ 异步处理
- 限流、熔断、兜底
增加缓存层 + 预热数据
如果我们所有数据都去读取数据库,数据库可能无法承受较大的流量,此时一个常见的优化就是增加缓存层。
在引入缓存层的时候,我们需要考虑缓存击穿、缓存穿透的可能性。
另外,我们在秒杀活动开始之前,可以手动将热点数据加载到缓存中,从而避免秒杀时去请求数据库。
MQ 异步处理
我们知道秒杀活动一般涉及抢购、下单、支付、发货等阶段,而抢购与后续的几个阶段是可以异步执行的。为了避免对下单、支付、发货等阶段产生影响,我们可以将抢购阶段与后续阶段用 MQ 进行解耦处理。当用户抢购成功后,往消息队列中丢入一台消息,随后再由订单系统消费进行下单处理。
通过各系统之间的解耦处理,我们可以将原本同步的处理方式变为异步处理,从而大大的减少了请求的处理时间,提高了系统的并发处理能力。其次,也能避免系统之间相互影响,提高了整体系统的稳定性。
限流、熔断、降级
限流:避免因为请求太多导致整个系统都无法工作。当超过设置的限流阈值时,我们则直接拒绝该请求,提示用户抢购失败。
熔断:指的是请求的错误次数超过阈值时,不再到用后端服务,直接返回失败。
降级:指的是当服务失败或异常后,返回指定的默认信息、
完整流程
为了预告用户两天后什么东西要参与秒杀,我们将要秒杀的商品的相关信息提前三天从数据库上架到缓存中,而且这个定时任务是每天晚上凌晨3点执行(趁不是高峰期时间)。
开启一个定时任务,将要秒杀的商品的相关信息提前三天从数据库上架到缓存中:
- ①gulimall-seckill每天凌晨三点远程调用gulimall-coupon服务的getLasts3DaySession()方法获取最近三天的秒杀活动————gulimall-coupon会查询“秒杀场次表”获取到最近三天的秒杀活动,然后根据活动id查询“秒杀场次和商品的关联表”获取到每一场秒杀活动参与秒杀的所有商品。将每一场秒杀活动的所有商品封装到SeckillSessionEntity的
List<SeckilSkuRellationEntity>
,然后三天的所有活动封装到List<SeckillSessionEntity>
里面返回。 - ②gulimall-seckill得到最近三天的秒杀活动后,将数据存到redis中————存到redis中的数据不仅仅是“这三天有几场秒杀活动,每个秒杀活动里面有多少商品”,还要把每件参与秒杀的商品的sku信息查询到存到