当前位置: 首页 > news >正文

系统设计-高频面试题(更新中...)

写在前面

🔥我把后端Java面试题做了一个汇总,有兴趣大家可以看看!这里👉

⭐️在反复复习面试题时,我发现不同资料的解释五花八门,容易造成概念混淆。尤其是很多总结性的文章和视频,要么冗长难记,要么过于简略,导致关键知识点含糊不清。

⭐️为了系统梳理知识,我决定撰写一份面试指南,不只是简单汇总,而是融入个人理解,层层拆解复杂概念,构建完整的知识体系。我希望它不仅帮助自己更自信地应对面试,也能为同行提供清晰、实用的参考。


系统设计面试题

B站千亿级点赞系统服务架构设计

在这里插入图片描述

思考方向:

明确需求 -> 系统架构 -> 数据存储 -> 高并发 -> 容灾降级 -> 异步处理

首先,点赞系统的核心业务能力主要有几类:

  • 用户可以对作品点赞、取消点赞,也支持点踩、取消点踩。
  • 用户需要查询点赞状态,比如某个稿件自己有没有点过赞,可以是单个查询也可以是批量查询。
  • 作品维度要能查点赞总数、点赞人列表。
  • 用户维度要能查自己的点赞列表,以及统计自己作品收到的总点赞数。

明确了这些之后,我会把整个系统拆成五个大的部分:

  1. 流量入口层:负责多机房流量调度和分配。
  2. 业务网关层:做统一鉴权、风控、限流,避免刷赞。
  3. 点赞服务层:对外暴露接口(RPC/HTTP),处理核心逻辑。
  4. 异步任务层:主要用于异步写入、缓存刷新、消息分发。
  5. 数据存储层:底层数据存储,包括数据库、缓存、KV、本地缓存。

在数据模型上,我会设计两张核心表:

  • 点赞记录表:存用户对作品的操作记录(用户 ID、作品 ID、操作类型、时间),可以按用户 ID、作品 ID 建联合索引。
  • 点赞计数表:存某个作品的累计点赞数和点踩数,按作品 ID 建索引。

存储我会分三层:

  • DB(比如 TiDB 这种分布式数据库),保证最终持久化和回源能力。
  • Redis 缓存,抗住大部分读流量,缓存点赞数、用户点赞列表,Key 一般是业务 ID+作品 ID。
  • 本地缓存(LocalCache),针对热点作品进一步加速,避免 Redis 被打爆。利用最小堆算法,在可配置的时间窗口范围内,统计出访问最频繁的缓存Key,并将热Key(Value)按照业务可接受的TTL存储在本地内存中。

高并发和热点的优化上:

  • 写优化:写请求走异步,点赞计数批量聚合再写 DB,降低 IO 压力。
  • 读优化:典型的 Cache-Aside 模式,配合热点识别,把热点 key 放到本地缓存。
  • 热点识别:自动识别热门作品,优先加速。

容灾和降级方面,因为点赞是用户强感知的功能:

  • 存储层我会做多级容灾,Redis、DB、KV 互相兜底。
  • 跨机房容灾,每个机房都有备份,可以快速切换。
  • 降级策略方面,如果存储挂了,接口不会直接报错,而是返回空值,保证体验,等服务恢复后再补写。

一致性这块,点赞这种业务允许小范围不一致:

  • 我们会有错误重试机制,关键链路比如点赞记录会无限重试。
  • 极少数情况下不同存储间数据不一致,也是可以接受的。

最后,吞吐量优化上,可以通过消息队列,把同步写转成异步写,进一步提升吞吐。关键链路会用事务消息加回查机制,保证用户操作不会丢。


如何设计一个百万人抽奖系统?

在这里插入图片描述

其实对于商品秒杀、抽奖活动、抢红包类的系统而言,架构设计的思路很多都是类似的,核心思路都是对于这种瞬时超高流量的系统,尽可能在负载均衡层就把99%的无效流量拦截掉。

然后在1%的流量进入核心业务服务后,此时每秒并发还是可能会上万,那么可以基于Redis实现核心业务逻辑 ,抗住上万并发。

最后对于类似秒杀商品发货、抽奖商品发货、红包资金转账之类的非常耗时的操作,完全可以基于MQ来限流削峰,后台有一个服务慢慢执行即可。

V1:负载均衡(分流)
当用户上升到百万的时候,我们就要加多台机器组成集群,用负载均衡把流量分散开。Nginx 都可以做,避免单台服务器过载。但是单纯加机器没用,因为瞬时高峰流量可能是平时的几十倍,所以我们还得继续。

V2:服务限流(防止重复抽奖)
限流的目的是防止瞬时流量把后端打挂。常见策略:

  • 用户级限流:比如一个用户一分钟只能抽一次,恶意脚本直接拦掉。
  • 可以在网关层用 Sentinel、或者直接在 Nginx 上做 IP 频率限制。

这样就避免了无效请求消耗资源。

V3:共享状态

其实像秒杀、抽奖、抢红包这类场景,都有一个共同点:奖品是有限的,可能 50 万人涌进来,前几百或者前几千请求就把奖品发完了,后续几十万请求都是无效的。如果还让这些请求继续打到后台服务上去执行业务逻辑,纯属浪费资源。

所以更合理的做法是:当奖品一旦抽完,就直接在 负载均衡层 把流量拦掉,返回“抽奖结束”。这样比如 50 万人同时请求,可能只有 2 万请求真正落到后台抽奖服务,剩下 48 万直接在入口层被挡住了,系统压力会小很多。

那这里就涉及一个问题:负载均衡层怎么知道奖品已经发完了?
答案就是要有一个 共享状态。常见的方式有两种:

  • Redis 存库存和抽奖状态,轻量级且能抗很高并发,抽奖服务更新状态后,负载均衡层查询即可。
  • 或者用 ZooKeeper 这类分布式协调组件,抽奖服务更新一个 znode 节点状态,负载均衡层通过 zk 客户端监听节点变化,立刻感知到奖品发完了。

一般来说,Redis 足够轻量、延迟更低,所以更多时候会首选 Redis。

V4:线程优化
在服务端,还需要调整线程池大小,不能太大也不能太小,需要通过压测找到一个平衡点。经验值可能是 200~500 之间,这样既能充分利用 CPU,又不会让线程上下文切换成本过高。

V5:抽奖逻辑
如果基于MySQL来实现核心的抽奖业务逻辑,抽奖服务频繁对MySQL进行增删改查,这一个MySQL实例也是很难抗住的。通常这种场景下,都是基于Redis来实现核心的业务逻辑。Redis 的 set 或者 list 结构很适合用来随机抽取中奖人,并且可以做到去重和弹出。这样性能很高,MySQL 完全不用顶住高并发。

V6:流量削峰
最后就是中奖通知。假设有一万人中奖,如果直接同步去调通知服务或者写 MySQL,瞬间压力很大。
这时候我们就把中奖结果写到 MQ(Kafka / RocketMQ / RabbitMQ)里,异步处理。通知服务慢慢消费,比如两个实例每秒发 100 条,1 万条也就延迟 1~2 分钟。用户体验基本没影响,但系统压力小很多。


如何从零开始设计一个秒杀系统

在这里插入图片描述

  1. 用户点击秒杀请求(HTTP/HTTPS):请求先到 CDN/WAF(防刷、限速、静态化)。

  2. 到网关:鉴权(登录、签名) + 幂等检查 + 人机校验(必要时)。

  3. 本地快速判断(缓存):检查活动是否开始/结束、是否在白名单、每用户限购数、是否已购买等(这些在 Redis /本地缓存)。

  4. Token 预占 / 本地速率控制:每台应用机器都在本地维护一个令牌桶,这样避免所有请求都打到 Redis。每个请求先尝试拿一个令牌,拿到才允许继续处理;没拿到就直接返回“繁忙”。

    如果想实现全局限流,QPS限制10w内,那就必须有一个全局统一的计数器,否则多台机器加起来会超标。Redis 就可以充当 全局令牌桶 的存储,定时往桶里投放令牌(比如每秒 10 万个)。

  5. Redis Lua 脚本做原子库存扣减:核心用 Redis 的 Lua 脚本做原子库存检查与扣减,且同时用 SETNX 控制单用户限购,避免超卖。

  6. 如果 Redis 扣减成功:立即返回“排队成功/下单中”给用户(低延迟体验),并把用户下单事件发到 MQ。

  7. 订单服务端 从 MQ 消费,做幂等检查、创建订单(DB 写),冻结/扣款流程、写支付/结算流程。若下单失败,触发补偿(返库存)或人工干预。

  8. 定期/实时对账:把 Redis 预占与落库的订单做对账(定时任务),若不一致触发补库存或差错处理。

库存 Key

  • seckill:stock:{goodsId} → 剩余库存数。
  • 扣减库存用 Lua 脚本原子操作:if stock > 0 then decr stock end

用户限购 Key

  • seckill:user:{activityId}:{userId} → 用户是否已买/买了多少。
  • SETNX / INCR 保证原子性,避免超购。

本地令牌桶 Key

  • seckill:token:{activityId} → 存放令牌数量,Redis + 本地桶配合削峰。
  • 也可以用 list/stream 做发放。

为什么不直接写库? -> 会成为瓶颈,容易死锁,异步 + MQ 能削峰并提高可用性。

如何保证最终一致性? -> Redis 记录 + MQ 消费幂等 + 周期性对账 + 补偿流程。

如何防刷? -> CDN + 验证码 + 设备指纹 + 行为风控 + 动态签名。

http://www.dtcms.com/a/465921.html

相关文章:

  • IntelliJ IDEA使用经验(十五):SQL脚本文件转为数据库控制台
  • 【实时Linux实战系列】内核跟踪点(Tracepoints)与用户态探针(UST)的协同调试
  • Linux 进程通信——消息队列与信号量
  • 备案ip 查询网站查询网站小说一键生成动漫
  • 做养生产品哪个网站好嘉兴网站建设网址
  • Vue3中实现全局双向绑定变量
  • C语言数据结构-排序
  • 【三维重建-对极几何】极线约束(Epipolar Constraint)
  • LeetCode算法日记 - Day 68: 猜数字大小II、矩阵中的最长递增路径
  • WSL 安装与卸载
  • app和微网站的对比河源网站建设
  • 新乡网站建设哪家好备案 网站名称
  • 版本控制器 git(5)--- git 标签管理
  • BShare HTTPS 集成与排查实战,从 SDK 接入到 iOS 真机调试(bshare https、签名、回调、抓包)
  • 基于同步压缩连续小波变换(SS-CWT)的微震图像去噪与起始检测
  • 太原网站建设工作室wordpress的内链插件
  • 简述网站开发流程 旅游做网站送邮箱
  • 湖北省住房建设厅网站网站备案登记查询系统
  • uri: mongodb://jack:123456@localhost://27017 数据库访问其他的写法
  • 在K8s中,seaweedFS 和 Longhorn 的比较
  • 146、【OS】【Nuttx】【周边】效果呈现方案解析:特殊变量$
  • 实现流水灯
  • 培 网站建设方案 doc台州seo网站推广
  • vue前端面试题——记录一次面试当中遇到的题(3)
  • Vuex的工作流程
  • 学习笔记:Vue Router 动态路由与参数匹配详解
  • seo怎样新建网站wordpress 底部模板
  • 高性能场景推荐使用PostgreSQL
  • 用一颗MCU跑通7B大模型:RISC-V+SRAM极致量化实战
  • 前端开发框架全景解析:从演进到实践与未来趋势