高性能系统面试题总结:CDN、负载均衡、分库分表与性能优化

这部分内容摘自 JavaGuide 下面几篇文章的重点:
高性能基础:
数据库性能优化:
回答高性能问题的通用思路
高性能面试题通常不会只考一个概念。面试官可能先问“系统接口很慢怎么优化”,再沿着入口流量、应用线程池、缓存、数据库和消息队列继续追问。
回答时可以沿着下面这条思路展开:
- 明确目标:要优化的是平均响应时间、P99、吞吐量、数据库压力,还是用户感知速度?
- 定位瓶颈:入口带宽、应用线程池、缓存命中率、慢 SQL、锁竞争、下游依赖和 MQ 积压,分别看哪些指标?
- 分层处理:CDN 和负载均衡解决入口问题,缓存和异步化降低应用压力,索引、读写分离和分库分表提升数据层能力。
- 说明代价:缓存会带来一致性问题,读写分离会带来主从延迟,分库分表会增加路由、事务和数据迁移成本。
- 验证效果:压测、灰度、监控、告警和回滚方案要一起准备。
题目没有给出业务量级时,可以先询问或主动做出合理假设,再说明方案。不要拿到“接口慢”就直接回答加缓存或分库分表。
高性能基础
⭐️什么是 CDN?为什么 CDN 能提升访问速度?
CDN(Content Delivery Network,内容分发网络)会把静态资源缓存到离用户更近的边缘节点。用户请求资源时,会优先访问合适的 CDN 节点;缓存没有命中时,节点才会回源获取资源。

CDN 能提升访问速度,主要靠下面几点:
- 就近访问:用户不需要跨地域访问源站,网络时延更低。
- 边缘缓存:静态资源命中缓存后可以直接返回。
- 减少回源:大量重复请求被拦在边缘节点,源站压力随之下降。
- 网络优化:CDN 服务商通常会做跨地域、跨运营商链路调度。
图片、CSS、JavaScript、字体和下载文件通常适合 CDN 缓存。HTML 是否长期缓存要谨慎:HTML 可能引用新的静态资源,旧 HTML 长时间留在缓存中,容易继续请求已经被删除的旧文件。
CDN 回源是什么意思?
CDN 节点没有缓存用户请求的资源,或者缓存已经过期时,会向源站请求资源,这个过程叫 回源。

两条常见链路如下:
- 缓存命中:用户 → CDN 节点 → 用户。
- 缓存未命中:用户 → CDN 节点 → 源站 → CDN 节点 → 用户。
回源量过大时,需要检查缓存规则、资源 URL 和刷新预热策略。资源没有设置合理的 Cache-Control、静态文件名没有内容 hash、热点资源发布后没有预热,都可能导致频繁回源。
⭐️HTML、JavaScript、CSS 和图片的缓存策略有什么区别?
推荐策略如下:
| 资源类型 | 推荐缓存策略 | 原因 |
|---|---|---|
| HTML | 不长期缓存,或者只做短时间缓存 | HTML 是入口文件,可能引用新的静态资源 |
| 带内容 hash 的 JS/CSS | 长期缓存,并设置 immutable | 内容变化后文件名也会变化 |
| 图片 | 根据更新频率设置较长缓存 | 图片通常比 HTML 更新得少 |
| sitemap、robots | 不缓存或者只做短时间缓存 | 搜索引擎需要尽快获取最新地址和抓取规则 |

静态站点部署时还有一个常见问题:部署脚本删除了旧 /assets/,但 CDN 或浏览器里仍然保留着旧 HTML,旧 HTML 再去请求旧 hash 文件就会返回 404,页面可能白屏。因此,部署时可以暂时保留旧静态资源,HTML 走短缓存,带内容 hash 的静态资源走长期缓存。
什么是负载均衡?
负载均衡会把请求分发到多个后端节点,避免流量集中到单台机器。它可以提升系统的吞吐能力、可用性和横向扩展能力。

常见实现方式分为两类:
- 服务端负载均衡:客户端先访问负载均衡器,再由负载均衡器转发到后端服务。Nginx、LVS、云负载均衡和 API 网关都属于这一类。
- 客户端负载均衡:客户端获得服务实例列表后,在本地选择目标实例。微服务内部调用经常采用这种方式。

负载均衡还要配合健康检查、慢节点剔除、节点预热和故障转移。只把请求平均分出去,但仍然向故障节点转发,系统依然不可用。
⭐️常见的负载均衡算法有哪些?
| 算法 | 思路 | 适用场景 |
|---|---|---|
| 随机 | 随机选择一个节点 | 节点性能和请求成本接近 |
| 轮询 | 按顺序分发请求 | 节点配置接近 |
| 加权轮询 | 配置更高的节点分配更多请求 | 后端机器配置不同 |
| 最小连接 | 优先选择连接数较少的节点 | 请求耗时差异较大 |
| 最快响应时间 | 优先选择响应更快的节点 | 更关注请求延迟 |
| 一致性哈希 | 同类请求尽量落到同一节点 | 缓存、会话和分片路由 |
一致性哈希在扩缩容时只需要迁移部分映射,适合缓存节点和分片路由。不过,选择算法时不能只看分布是否均匀,还要处理节点健康、热点请求、慢节点和会话粘滞等问题。

数据库性能优化
⭐️什么是读写分离?它解决了什么问题?
读写分离把写请求交给主库,把部分读请求分散到从库,主要用于缓解 读多写少场景下的主库读压力。

典型流程如下:
- 主库处理写请求。
- 主库通过 binlog 将数据变更复制到从库。
- 应用或数据库代理把允许读旧数据的查询路由到从库。
读写分离会引入主从延迟。刚写完就要读取最新结果的请求,可以在一段时间内读主库,或者让业务接受短暂的最终一致性。从库也不是免费的读能力:报表、全表扫描和慢 SQL 同样会占用从库资源,并可能影响复制进度。
MySQL 主从复制的基本原理是什么?
MySQL 主从复制依赖 binlog。主库记录数据变更,从库接收并重放这些变更。

可以按 3 个阶段理解:
- 主库提交事务,并把变更写入 binlog。
- 从库 I/O receiver 线程接收 binlog,写入 relay log。
- 从库 applier 线程读取 relay log,把变更应用到本地数据。
主从延迟可能出现在网络传输、从库写 relay log 和从库重放事务的任意阶段。
⭐️什么情况下会出现主从延迟?
常见原因包括:
- 从库机器性能比主库差。
- 从库承担了过多或过重的读请求。
- 主库产生了大事务,从库重放耗时很长。
- 主从之间网络延迟较高或者网络发生抖动。
- 从库复制线程的并行度不足。
- 从库磁盘 I/O 或 CPU 已经达到瓶颈。
处理时应先确认延迟发生在接收阶段还是重放阶段,再针对性地提升从库规格、治理慢 SQL 和大事务、分散查询、调整并行复制参数。核心写后读链路仍然可以路由到主库,不能假设半同步复制会让从库立即可读。
什么是分库分表?
分库分表把数据拆到多个库或多张表中,用于解决单库单表容量过大、读写压力过高的问题。
常见拆分方式如下:
- 垂直分库:按业务拆库,例如用户库、订单库、商品库。
- 水平分库:把同一张逻辑表的数据按规则分散到多个库。
- 垂直分表:按字段拆表,把大字段或低频字段拆出去。
- 水平分表:把同一张逻辑表的记录按行拆成多张表。
水平分库和水平分表经常一起使用:先按分片键路由到某个库,再访问这个库中的具体分表。
⭐️什么时候需要分库分表?
分库分表应该放在常规优化之后考虑。典型场景包括:
- 单表数据量持续增长,核心查询和写入已经明显变慢。
- 单库容量、连接数或写入能力接近瓶颈。
- 通过索引、SQL 优化、缓存和读写分离仍然无法满足容量或吞吐要求。
- 业务存在稳定的分片维度,例如用户 ID、租户 ID 或订单 ID。
不能只根据“单表达到某个固定行数”决定是否拆分。表结构、索引数量、记录大小、硬件配置、查询方式和延迟目标都会影响实际容量。
分库分表会带来哪些问题?
常见问题包括:
- 跨库 Join、聚合、排序和分页变复杂。
- 分布式事务和数据一致性处理变复杂。
- 全局唯一 ID 需要单独设计。
- 扩容和数据迁移成本高。
- 分片键选错可能造成数据倾斜和热点。
- 原有唯一约束可能无法跨分片直接保证。
ShardingSphere、MyCat 或自研中间层可以处理路由、归并和分布式主键,但不会消除业务复杂度。设计阶段仍然需要说明跨分片查询、数据迁移和故障恢复如何完成。

⭐️分片键应该如何选择?
分片键应尽量满足下面几个要求:
- 覆盖主要查询:核心查询能带上分片键,避免扫描多个分片。
- 分布足够离散:数据和请求不要集中到少数分片。
- 长期保持稳定:分片键变化会触发跨分片迁移。
- 方便后续扩展:扩容时能够控制迁移范围和路由变化。
订单系统可以把用户 ID、商家 ID 或订单 ID 作为候选,但最终选择取决于主要查询链路。按用户 ID 分片方便查询用户订单,按订单 ID 分片方便按订单查询,两者对应的跨分片场景不同。
SQL 优化有哪些常见手段?
常见手段包括:
- 只查询需要的字段,避免滥用
SELECT *。 - 为高频查询条件和排序条件设计合适索引。
- 使用覆盖索引减少回表。
- 避免在索引列上使用不必要的函数和表达式。
- 使用批量操作减少网络往返。
- 减少不必要的大表 Join、排序和临时表。
- 根据业务修改深度分页方式。
- 通过慢查询日志和执行计划定位瓶颈。
回答 SQL 优化问题时,可以先说如何定位,再谈优化动作:先通过监控和慢查询日志找到目标 SQL,然后使用 EXPLAIN 或 EXPLAIN ANALYZE 查看访问方式、索引、扫描行数、排序和回表情况,最后修改索引、SQL 或表结构,并用真实执行数据验证结果。

⭐️哪些情况可能导致索引没有发挥作用?
常见情况包括:
- 对索引列使用函数或表达式。
- 查询条件发生隐式类型转换。
- 使用前导模糊匹配,例如
LIKE '%abc'。 - 联合索引没有满足最左前缀原则。
- 范围查询之后的联合索引列无法继续用于有序匹配。
- 查询条件选择性太差,优化器判断全表扫描成本更低。
- 统计信息不准确,优化器选择了不合适的执行计划。
“索引失效”只是一个笼统说法。有些情况下索引仍然被使用,但只能扫描大量索引项;有些情况下优化器主动放弃了索引。最终应结合 EXPLAIN、真实扫描行数和耗时判断。
什么是深度分页?为什么会慢?
深度分页指页码非常靠后,例如:
SELECT * FROM orders ORDER BY id LIMIT 1000000, 10;数据库需要先找到并跳过前面的 1000000 条记录,再返回 10 条。查询如果还涉及回表、排序或临时表,偏移量越大,浪费的工作越多。

⭐️深度分页如何优化?
| 方案 | 思路 | 适用场景 |
|---|---|---|
| 游标分页 | 使用上一页最后一条记录的排序键继续查 | 信息流、只需要上一页/下一页 |
| 延迟关联 | 先在覆盖索引上分页,再关联原表 | 大偏移且仍需传统页码 |
| 覆盖索引 | 查询字段全部位于索引中,避免回表 | 返回字段较少 |
| 限制页数 | 限制最大可翻页范围 | 搜索、日志等无需无限翻页的场景 |
游标分页应使用稳定且唯一的排序键。例如按 created_at 倒序时,可以同时带上 id,避免时间相同的记录在翻页时重复或遗漏。
SELECT id, created_at, amount
FROM orders
WHERE (created_at, id) < (?, ?)
ORDER BY created_at DESC, id DESC
LIMIT 20;如果产品必须支持任意跳页,优化空间会小很多;移动端信息流改成“加载下一页”后,游标分页通常更合适。
什么是数据冷热分离?
数据冷热分离会把高频访问的热数据和低频访问的冷数据分开存储。热数据留在主业务库或高性能存储中,冷数据迁移到成本更低、查询频率更低的存储中。
典型场景包括:
- 订单系统把近期订单留在在线库,历史订单转入归档库。
- 日志系统保留近期可检索日志,历史日志转入对象存储。
- 内容系统把热门内容和历史低频内容分层存储。

冷热分离更关注数据生命周期和存储成本,分库分表更关注容量和并发扩展。两者解决的问题不同。
⭐️冷热分离迁移时如何保证一致性?
可以采用分批迁移、校验和补偿的方式:
- 按时间或 ID 范围分批迁移,避免大事务长时间占用资源。
- 记录迁移范围和任务状态,任务失败后能够重试。
- 迁移后校验记录数量、主键范围和关键字段摘要。
- 查询层根据时间、状态或路由表决定访问热库还是冷库。
- 观察一段时间后再删除热库中的冷数据,删除前保留回滚能力。
- 通过定期对账任务发现并修复不一致数据。
迁移期间如果数据仍然会更新,还需要明确写入规则:冻结冷数据更新、同步变更日志,或者在读取时合并新旧存储中的结果。
系统设计综合题
⭐️如何设计一个高性能订单系统?
可以沿着订单请求的完整链路回答:
- 明确目标:先确认峰值 QPS、订单量、响应时间和库存一致性要求。
- 入口层:静态资源交给 CDN,API 请求通过负载均衡进入服务集群。
- 应用层:核心写接口做好限流和幂等,热点读请求使用缓存。
- 数据库层:先优化索引和 SQL;读压力高时做读写分离,单库单表达到瓶颈后再考虑分库分表。
- 查询层:历史订单可以做冷热分离,列表查询优先采用游标分页。
- 异步层:订单创建后的通知、积分和部分风控动作通过 MQ 异步处理。
- 稳定性:监控 QPS、P99、错误率、慢 SQL、连接池、缓存命中率和消息积压。
方案必须说明一致性取舍。例如,库存扣减和订单状态属于核心链路,不能仅依靠异步消息“最终会成功”;通知和积分通常可以异步处理,并通过重试和补偿保证最终完成。
高性能优化的核心思路是什么?
高性能优化可以从 6 个方向展开:
- 减少访问距离:CDN、就近接入。
- 分散流量压力:负载均衡、服务水平扩容。
- 减少重复计算和读取:缓存、预计算、批处理。
- 降低数据层压力:索引、SQL 优化、读写分离、冷热分离和分库分表。
- 削峰和异步化:消息队列、任务队列。
- 持续测量和验证:监控、压测、灰度和容量评估。
优化前先定位瓶颈,修改后再比较吞吐、延迟、错误率和资源使用率。没有指标的“优化”很难判断是否有效,也可能只是把压力从一个组件转移到了另一个组件。
写在最后
感谢你能看到这里,也希望这篇文章对你有点用。
JavaGuide 坚持更新 6 年多,近 6000 次提交、600+ 位贡献者一起打磨。如果这些内容对你有帮助,非常欢迎点个免费的 Star 支持下(完全自愿,觉得有收获再点就好):GitHub | Gitee。
如果你想要付费支持/面试辅导(比如简历优化、一对一提问、高频考点突击资料等)的话,欢迎了解我的知识星球。已经坚持维护六年,内容持续更新,虽白菜价(0.4元/天)但质量很高,主打一个良心!

