📽️

项目面试指南

项目面试指南


一、项目介绍

1.1 STAR 法则

要素
说明
示例
Situation
项目背景
公司电商平台日活 100 万
Task
你的任务
负责订单系统重构
Action
采取的行动
引入分库分表、消息队列
Result
取得的成果
QPS 提升 10 倍,延迟降低 50%

1.2 项目介绍模板

1. 项目背景(1-2句)
   - 业务场景、用户规模

2. 技术架构(重点)
   - 整体架构图
   - 核心技术栈

3. 你的职责
   - 负责的模块
   - 解决的核心问题

4. 技术亮点
   - 性能优化
   - 架构设计

5. 项目成果
   - 量化指标

1.3 架构图讲解技巧

讲解顺序: 1. 整体概览:先介绍系统整体架构 2. 分层说明:从上到下或从左到右 3. 核心链路:重点讲解核心业务流程 4. 技术亮点:突出你负责的部分
示例讲解
这是我们订单系统的整体架构:

1. 接入层:Nginx 做负载均衡,网关负责鉴权和限流
2. 服务层:采用微服务架构,订单、库存、支付独立部署
3. 中间件:Redis 做缓存,Kafka 做异步解耦
4. 数据层:MySQL 分库分表,ES 做订单搜索

我主要负责订单服务,核心解决了高并发下的库存超卖问题...

1.4 项目亮点/创新点

常见亮点类型: | 类型 | 示例 | |——|——| | 性能优化 | 接口延迟从 500ms 降到 50ms | | 架构改进 | 单体拆分微服务,支持独立扩展 | | 技术攻坚 | 解决分布式事务一致性问题 | | 工具建设 | 开发自动化测试框架 | | 成本优化 | 服务器成本降低 30% |

1.5 收获与反思

回答框架
技术收获:
- 深入理解了 XXX 技术原理
- 掌握了 XXX 问题的解决方案

业务收获:
- 理解了 XXX 业务场景
- 学会了如何平衡技术和业务

反思改进:
- 如果重新做,会在 XXX 方面做得更好
- 发现了 XXX 问题,后续可以优化

1.6 技术方案评审要点

评审维度: | 维度 | 关注点 | |——|——–| | 功能性 | 是否满足业务需求 | | 可靠性 | 异常处理、容错设计 | | 性能 | 响应时间、吞吐量 | | 可扩展性 | 未来业务增长支持 | | 安全性 | 数据安全、接口安全 | | 可维护性 | 代码质量、文档完善 | | 成本 | 开发成本、运维成本 |
评审流程
1. 方案背景和目标
2. 技术选型和对比
3. 详细设计(架构图、时序图、数据模型)
4. 风险评估和应对
5. 里程碑和排期

1.7 技术选型理由

场景
选型
理由
缓存
Redis
高性能、丰富数据结构
消息队列
Kafka
高吞吐、持久化
搜索
Elasticsearch
全文检索、聚合分析
数据库
MySQL + 分库分表
成熟稳定、团队熟悉

二、系统设计原则

2.1 高可用设计

核心思路:冗余 + 故障转移
层级
方案
应用层
多实例部署、负载均衡
缓存层
Redis 集群、主从
数据库
主从复制、读写分离
服务层
熔断、降级、限流
可用性计算
可用性 = MTBF / (MTBF + MTTR)
99.9% = 8.76 小时/年 停机
99.99% = 52.6 分钟/年 停机

2.2 高并发设计

策略
说明
缓存
减少数据库压力
异步
消息队列削峰
分流
CDN、负载均衡
分库分表
数据水平扩展
池化
连接池、线程池

2.3 容量评估

日活用户:100 万
日均请求:1000 万
峰值 QPS = 日均 QPS × 峰值系数
        = (1000/ 86400) × 101157 × 10 = 11570 QPS

单机 QPS1000
需要机器:12 台(预留 buffer)

2.4 可扩展性设计

策略
说明
水平扩展
增加机器数量
垂直扩展
升级单机配置
无状态设计
服务不保存状态,便于扩展
分库分表
数据水平拆分
微服务拆分
服务独立部署扩展
无状态设计原则: - Session 存储在 Redis - 文件存储在对象存储 - 配置存储在配置中心

2.5 一致性设计

一致性级别
说明
适用场景
强一致性
写入立即可见
金融交易
最终一致性
一段时间后一致
社交动态
因果一致性
因果相关操作有序
评论回复
实现方案: - 强一致:同步复制、分布式事务 - 最终一致:异步复制、消息队列

三、微服务

3.1 服务拆分原则

原则
说明
单一职责
一个服务只做一件事
高内聚低耦合
减少服务间依赖
业务边界
按领域模型拆分
数据独立
每个服务独立数据库

3.2 服务注册与发现

服务启动 → 注册到注册中心(Nacos/Consul)
         ↓
调用方从注册中心获取服务列表
         ↓
负载均衡选择实例调用

3.3 API 网关

功能: - 路由转发 - 认证鉴权 - 限流熔断 - 日志监控 - 协议转换
常用组件:Kong、Nginx、Spring Cloud Gateway

3.4 配置中心设计

组件
特点
Nacos
阿里开源,配置 + 注册中心
Apollo
携程开源,功能丰富
Spring Cloud Config
Spring 生态
核心功能: - 配置集中管理 - 动态更新(不重启) - 版本管理与回滚 - 灰度发布 - 权限控制

3.5 服务间通信

方式
特点
适用场景
HTTP/REST
简单、通用
跨语言、外部接口
RPC(gRPC)
高性能、强类型
内部服务调用
消息队列
异步、解耦
异步处理、削峰

3.6 服务版本管理

版本策略: - URL 版本:/api/v1/users - Header 版本:Accept: application/vnd.api.v1+json - 参数版本:/api/users?version=1
兼容性原则: - 新增字段不破坏旧版本 - 废弃字段标记 deprecated - 重大变更发布新版本

四、消息队列

4.1 使用场景

场景
说明
异步处理
注册后发邮件、短信
削峰填谷
秒杀订单入队
系统解耦
订单 → 库存、物流
日志收集
应用日志 → Kafka → ES

4.2 消息可靠性

生产者
1. 确认机制(acks=all)
2. 重试机制
3. 本地消息表
Broker
1. 持久化
2. 副本机制
消费者
1. 手动确认
2. 幂等处理

4.3 消息顺序性

Kafka: - 单 Partition 内有序 - 相同 Key 发送到同一 Partition
producer.send(new ProducerRecord<>(topic, orderId, message));

4.4 消息积压处理

  1. 临时扩容消费者
  1. 跳过非关键消息
  1. 转存后离线处理

4.5 Kafka 高性能原理

技术
说明
顺序写
磁盘顺序写性能高
零拷贝
sendfile 减少拷贝
批量发送
减少网络开销
分区并行
多 Partition 并行消费
页缓存
利用 OS 页缓存

4.6 消息幂等性

问题:消息可能重复消费
解决方案: | 方案 | 说明 | |——|——| | 唯一 ID | 消息携带唯一 ID,消费前检查 | | 数据库唯一索引 | 业务字段唯一约束 | | Redis 去重 | SETNX 记录已处理消息 | | 状态机 | 状态只能单向流转 |
def consume(message):
    msg_id = message.id
    # Redis 去重
    if not redis.setnx(f"msg:{msg_id}", 1, ex=86400):
        return  # 已处理

    # 处理业务逻辑
    process(message)

4.7 延迟消息实现

方案
说明
RocketMQ 延迟级别
内置 18 个延迟级别
RabbitMQ 死信队列
TTL + 死信交换机
Redis ZSet
score 为执行时间
时间轮
高效定时任务
# Redis ZSet 实现
def delay_message(msg, delay_seconds):
    execute_time = time.time() + delay_seconds
    redis.zadd("delay_queue", {msg: execute_time})

# 消费者轮询
while True:
    now = time.time()
    messages = redis.zrangebyscore("delay_queue", 0, now)
    for msg in messages:
        process(msg)
        redis.zrem("delay_queue", msg)

4.8 Kafka vs RabbitMQ vs RocketMQ

特性
Kafka
RabbitMQ
RocketMQ
吞吐量
极高
中等
延迟
毫秒级
微秒级
毫秒级
消息顺序
Partition 内有序
队列内有序
队列内有序
延迟消息
不支持
支持
支持
事务消息
支持
支持
支持
适用场景
日志、大数据
业务消息
电商、金融

五、分布式

5.1 CAP 理论

特性
说明
C(一致性)
所有节点数据一致
A(可用性)
请求都能得到响应
P(分区容错)
网络分区时系统可用
三选二:分布式系统必须容忍 P,在 C 和 A 间权衡
系统
选择
ZooKeeper
CP
Eureka
AP
Redis Cluster
AP

5.2 BASE 理论

特性
说明
BA(基本可用)
允许部分功能降级
S(软状态)
允许中间状态
E(最终一致)
最终数据一致

5.3 分布式事务

方案
原理
适用场景
2PC
协调者两阶段提交
强一致要求
TCC
Try-Confirm-Cancel
高并发
Saga
补偿事务
长事务
本地消息表
消息 + 定时任务
异步场景
TCC 示例
Try:预留资源(冻结库存)
Confirm:确认执行(扣减库存)
Cancel:取消释放(解冻库存)

5.4 分布式锁

Redis 实现
-- 加锁
SET lock_key unique_value NX EX 30

-- 解锁(Lua 保证原子性)
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
end
ZooKeeper 实现
创建临时顺序节点
判断是否最小节点
是 → 获得锁
否 → 监听前一个节点

5.5 分布式 ID

方案
优点
缺点
UUID
简单
无序、太长
数据库自增
简单
性能瓶颈
雪花算法
趋势递增、高性能
时钟回拨
Leaf
高可用
依赖外部服务

5.6 一致性哈希

解决问题:节点增减时减少数据迁移
哈希环:0 ~ 2^32-1
节点映射到环上
数据顺时针找到第一个节点

虚拟节点:解决数据倾斜

5.7 Raft 协议

核心:Leader 选举 + 日志复制
1. 选举:获得多数票成为 Leader
2. 日志复制:Leader 复制日志到 Follower
3. 提交:多数确认后提交

5.8 Paxos 协议

角色: - Proposer:提出提案 - Acceptor:接受提案 - Learner:学习已通过的提案
两阶段: 1. Prepare:Proposer 发送提案编号 2. Accept:Acceptor 接受最高编号的提案
与 Raft 对比: | 特性 | Paxos | Raft | |——|——-|——| | 复杂度 | 高 | 低 | | 理解难度 | 难 | 易 | | Leader | 可选 | 必须 | | 工程实现 | 复杂 | 简单 |

5.9 ZooKeeper 原理与应用

核心特性: - 顺序一致性 - 原子性 - 单一视图 - 可靠性 - 实时性(最终一致)
应用场景: | 场景 | 实现方式 | |——|———-| | 配置中心 | 持久节点 + Watch | | 服务注册 | 临时节点 | | 分布式锁 | 临时顺序节点 | | Leader 选举 | 临时顺序节点 |
/services
  /user-service
    /instance-1  (临时节点)
    /instance-2  (临时节点)

六、缓存设计

6.1 缓存策略

策略
说明
Cache-Aside
先查缓存,未命中查库并写缓存
Read-Through
缓存层负责读取
Write-Through
同步写缓存和数据库
Write-Behind
异步批量写数据库

6.2 缓存一致性

推荐方案:先更新数据库,再删除缓存
def update(data):
    db.update(data)
    cache.delete(key)

    # 延迟双删(可选)
    time.sleep(0.5)
    cache.delete(key)
为什么删除而不是更新: - 避免并发写导致数据不一致 - 懒加载,减少无效更新

6.3 多级缓存

请求 → 本地缓存(Caffeine) → Redis → 数据库

6.4 热点数据处理

方案
说明
本地缓存
减少 Redis 压力
多副本
热点 Key 分散到多个 Key
读写分离
从库分担读压力

6.5 缓存预热

场景:系统启动时缓存为空,大量请求打到数据库
方案: 1. 启动预热:启动时加载热点数据 2. 定时预热:定时任务刷新缓存 3. 手动预热:运维工具触发
def warm_up_cache():
    # 加载热点商品
    hot_products = db.query("SELECT * FROM products WHERE is_hot = 1")
    for product in hot_products:
        cache.set(f"product:{product.id}", product, ex=3600)

    # 加载热门用户
    hot_users = db.query("SELECT * FROM users ORDER BY followers DESC LIMIT 1000")
    for user in hot_users:
        cache.set(f"user:{user.id}", user, ex=3600)

七、限流熔断

7.1 限流算法

算法
说明
特点
计数器
固定窗口计数
临界问题
滑动窗口
滑动时间窗口
平滑
漏桶
固定速率处理
平滑输出
令牌桶
固定速率放令牌
允许突发
令牌桶实现
class TokenBucket:
    def __init__(self, rate, capacity):
        self.rate = rate          # 令牌生成速率
        self.capacity = capacity  # 桶容量
        self.tokens = capacity
        self.last_time = time.time()

    def acquire(self):
        now = time.time()
        # 添加令牌
        self.tokens = min(self.capacity,
                         self.tokens + (now - self.last_time) * self.rate)
        self.last_time = now

        if self.tokens >= 1:
            self.tokens -= 1
            return True
        return False

7.2 熔断器

状态转换
Closed → Open → Half-Open → Closed
  ↓       ↓         ↓
正常    熔断    尝试恢复
Hystrix/Sentinel: - 失败率超阈值 → 熔断 - 超时时间后 → 半开 - 成功 → 关闭

7.3 降级策略

策略
说明
返回默认值
返回兜底数据
返回缓存
返回旧缓存数据
功能降级
关闭非核心功能
页面降级
返回静态页面

7.4 服务隔离

方式
说明
优缺点
线程池隔离
每个服务独立线程池
隔离性好,开销大
信号量隔离
限制并发数
开销小,无法超时
// Hystrix 线程池隔离
@HystrixCommand(
    threadPoolKey = "userServicePool",
    threadPoolProperties = {
        @HystrixProperty(name = "coreSize", value = "10"),
        @HystrixProperty(name = "maxQueueSize", value = "100")
    }
)
public User getUser(Long id) {
    return userService.getUser(id);
}

八、性能优化

8.1 接口优化

方向
方法
减少 IO
批量查询、缓存
异步处理
非核心逻辑异步化
并行处理
多线程并行查询
减少数据
按需返回字段

8.2 数据库优化

方向
方法
索引
合理建索引
SQL
避免慢查询
连接池
复用连接
读写分离
分担读压力
分库分表
水平扩展

8.3 线上问题排查

CPU 100%
1. top -c 找到进程
2. top -Hp <pid> 找到线程
3. printf '%x' <tid>16 进制
4. jstack <pid> | grep <tid> 查看堆栈
内存泄漏
1. jmap -heap <pid> 查看堆使用
2. jmap -dump:format=b,file=heap.bin <pid>
3. MAT 分析 dump 文件
GC 问题
1. jstat -gc <pid> 1000 查看 GC 情况
2. 分析 GC 日志
3. 调整堆大小、GC 算法

8.4 JVM 调优

常用参数
# 堆内存
-Xms4g -Xmx4g          # 初始和最大堆
-Xmn2g                  # 新生代大小

# GC 选择
-XX:+UseG1GC           # G1 收集器
-XX:+UseZGC            # ZGC(低延迟)

# GC 日志
-Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=10M
调优思路: 1. 确定性能目标(吞吐量/延迟) 2. 选择合适的 GC 算法 3. 调整堆大小和比例 4. 分析 GC 日志优化

8.5 压测与性能评估

压测工具: | 工具 | 特点 | |——|——| | JMeter | 功能丰富,GUI | | wrk | 高性能,命令行 | | ab | 简单,Apache 自带 | | Locust | Python,分布式 |
关键指标: | 指标 | 说明 | |——|——| | QPS | 每秒请求数 | | TPS | 每秒事务数 | | RT | 响应时间 | | P99 | 99% 请求的响应时间 | | 错误率 | 失败请求占比 |
# wrk 示例
wrk -t12 -c400 -d30s http://localhost:8080/api/users

八点五、监控告警

8.6 日志收集与分析(ELK)

架构
应用日志 → Filebeat → Kafka → Logstash → Elasticsearch → Kibana
组件职责: | 组件 | 职责 | |——|——| | Filebeat | 日志采集,轻量级 | | Logstash | 日志解析、转换 | | Elasticsearch | 存储、检索 | | Kibana | 可视化、分析 |
日志规范
{
  "timestamp": "2026-01-09T10:00:00Z",
  "level": "ERROR",
  "service": "order-service",
  "traceId": "abc123",
  "message": "订单创建失败",
  "exception": "..."
}

8.7 链路追踪(Jaeger/Zipkin)

核心概念: | 概念 | 说明 | |——|——| | Trace | 一次完整请求链路 | | Span | 链路中的一个操作 | | TraceId | 链路唯一标识 | | SpanId | 操作唯一标识 | | ParentSpanId | 父操作标识 |
实现原理
请求进入 → 生成 TraceId → 传递到下游服务 → 收集 Span → 聚合展示

8.8 指标监控(Prometheus/Grafana)

Prometheus 架构
应用暴露 /metrics → Prometheus 拉取 → 存储时序数据 → Grafana 展示
                                    ↓
                              Alertmanager 告警
四种指标类型: | 类型 | 说明 | 示例 | |——|——|——| | Counter | 只增不减 | 请求总数 | | Gauge | 可增可减 | 当前连接数 | | Histogram | 分布统计 | 响应时间分布 | | Summary | 分位数统计 | P99 延迟 |

8.9 告警设计

告警分级: | 级别 | 说明 | 响应时间 | |——|——|———-| | P0 | 核心业务不可用 | 5 分钟 | | P1 | 重要功能受损 | 30 分钟 | | P2 | 非核心功能异常 | 2 小时 | | P3 | 预警类 | 下个工作日 |
告警规则示例
# Prometheus 告警规则
groups:
-name: api-alerts
rules:
-alert: HighErrorRate
expr: rate(http_requests_total{status="500"}[5m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary:"高错误率告警"

九、场景设计题

9.1 秒杀系统

核心挑战:高并发、超卖、重复下单
架构设计
用户 → CDN → Nginx → 网关 → 秒杀服务 → Redis → MQ → 订单服务
关键技术: | 问题 | 方案 | |——|——| | 高并发 | 页面静态化、CDN、限流 | | 超卖 | Redis 预扣库存 + Lua 原子操作 | | 重复下单 | 用户 + 商品 唯一索引 | | 数据库压力 | 异步下单(MQ) |
Redis 扣库存
local stock = redis.call('get', KEYS[1])
if tonumber(stock) > 0 then
    redis.call('decr', KEYS[1])
    return 1
end
return 0

9.2 短链服务

核心功能:长链接 → 短链接 → 重定向
设计方案
1. 生成短码:Base62(自增ID) 或 哈希
2. 存储:短码 → 长链接
3. 访问:302 重定向
短码生成
CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

def encode(num):
    result = []
    while num:
        result.append(CHARS[num % 62])
        num //= 62
    return ''.join(reversed(result))

9.3 Feed 流系统

推模式:写扩散
发布动态 → 写入所有粉丝的 Feed 列表
优点:读取快
缺点:写放大(大 V 问题)
拉模式:读扩散
读取 Feed → 聚合关注人的动态
优点:写入简单
缺点:读取慢
推拉结合: - 普通用户:推模式 - 大 V:拉模式

9.4 订单系统

核心问题: | 问题 | 方案 | |——|——| | 订单超时取消 | 延迟队列(RocketMQ/Redis ZSet) | | 库存扣减 | 预扣 → 确认/回滚 | | 幂等性 | 订单号唯一索引 | | 分库分表 | 按用户 ID 分片 |

9.5 支付系统

核心问题: | 问题 | 方案 | |——|——| | 重复支付 | 支付单号幂等 | | 掉单 | 对账 + 补单 | | 一致性 | 本地事务 + 异步通知 | | 安全 | 签名验签、HTTPS |

9.6 抢红包系统

设计要点: 1. 预分配:红包创建时预先分配金额 2. 原子扣减:Redis Lua 保证原子性 3. 异步入账:消息队列异步处理
-- 抢红包 Lua 脚本
local remaining = redis.call('hget', KEYS[1], 'remaining')
if tonumber(remaining) > 0 then
    local amount = redis.call('lpop', KEYS[2])
    if amount then
        redis.call('hincrby', KEYS[1], 'remaining', -1)
        return amount
    end
end
return nil

9.7 评论系统

数据模型
-- 评论表
CREATE TABLE comments (
    id BIGINT PRIMARY KEY,
    content TEXT,
    user_id BIGINT,
    target_id BIGINT,      -- 被评论对象
    parent_id BIGINT,      -- 父评论(楼中楼)
    root_id BIGINT,        -- 根评论
    created_at TIMESTAMP
);
分页方案: - 游标分页(推荐):WHERE id < last_id ORDER BY id DESC LIMIT 20 - 偏移分页:LIMIT 20 OFFSET 100(大偏移性能差)

9.8 排行榜系统

Redis ZSet 实现
# 更新分数
redis.zadd("leaderboard", {user_id: score})

# 获取排名(从 0 开始)
rank = redis.zrevrank("leaderboard", user_id)

# 获取 Top N
top_users = redis.zrevrange("leaderboard", 0, 9, withscores=True)

# 获取用户附近排名
start = max(0, rank - 5)
nearby = redis.zrevrange("leaderboard", start, rank + 5, withscores=True)

9.9 搜索系统

架构
数据源 → 数据同步 → Elasticsearch → 搜索服务 → 用户
核心功能: | 功能 | 实现 | |——|——| | 全文检索 | ES 倒排索引 | | 分词 | IK 分词器 | | 高亮 | highlight | | 聚合 | aggregations | | 排序 | 相关性 + 业务权重 |

9.10 定时任务系统

方案
适用场景
Cron
单机定时
Quartz
分布式定时
XXL-JOB
可视化调度
时间轮
高性能延迟任务
分布式定时任务要点: - 任务只执行一次(分布式锁) - 任务失败重试 - 任务监控告警

9.11 消息推送系统

架构
业务系统 → 推送服务 → 长连接网关 → 客户端
                   ↘ 第三方推送(APNs/FCM
长连接方案: | 方案 | 特点 | |——|——| | WebSocket | 双向通信,浏览器支持 | | MQTT | 轻量级,IoT 常用 | | 自定义协议 | 灵活,开发成本高 |

9.12 文件存储系统

架构
客户端 → 上传服务 → 对象存储(OSS/S3)
              ↓
         元数据服务 → 数据库
大文件上传: 1. 分片上传:大文件切分为小块 2. 断点续传:记录已上传分片 3. 秒传:MD5 校验,相同文件直接返回

十、通用问题

10.1 接口幂等性

方案
说明
唯一索引
数据库唯一约束
Token 机制
先获取 Token,使用后删除
状态机
状态只能单向流转
乐观锁
version 版本号
Token 实现
# 获取 Token
token = uuid.uuid4()
redis.set(f"token:{token}", 1, ex=300)
return token

# 使用 Token
if redis.delete(f"token:{token}"):
    # 执行业务
else:
    # 重复请求

10.2 接口安全

方案
说明
HTTPS
传输加密
签名
防篡改
时间戳
防重放
Token
身份认证
限流
防刷

10.3 灰度发布

方案
说明
用户灰度
按用户 ID 百分比
流量灰度
按请求百分比
机器灰度
部分机器部署新版本

10.4 AB 测试

实现方式: 1. 流量分桶:用户 ID 哈希分配到不同桶 2. 实验配置:配置中心管理实验参数 3. 数据收集:埋点收集用户行为 4. 效果分析:统计分析确定最优方案
def get_experiment_group(user_id, experiment_name):
    bucket = hash(f"{user_id}:{experiment_name}") % 100
    if bucket < 10:
        return "control"  # 对照组 10%
    elif bucket < 20:
        return "treatment_a"  # 实验组A 10%
    else:
        return "treatment_b"  # 实验组B 80%

10.5 项目亮点回答模板

1. 背景:为什么要做这个优化/设计
2. 方案:采用了什么技术方案
3. 实现:关键的技术细节
4. 效果:量化的改进数据
5. 思考:方案的优缺点、改进空间
示例
背景:订单查询接口 P99 延迟达到 500ms,影响用户体验
方案:引入多级缓存(本地缓存 + Redis)
实现:
  - 本地缓存使用 Caffeine,TTL 10s
  - Redis 缓存 TTL 5min
  - 缓存更新采用 Cache-Aside 模式
效果:P99 延迟降低到 50ms,数据库 QPS 下降 80%
思考:需要注意缓存一致性问题,采用延迟双删保证

10.6 如何设计高可用系统

核心策略: | 层面 | 方案 | |——|——| | 冗余 | 多实例、多机房、多活 | | 隔离 | 服务隔离、资源隔离 | | 限流 | 保护系统不被压垮 | | 熔断 | 快速失败,避免级联故障 | | 降级 | 有损服务优于无服务 | | 监控 | 快速发现和定位问题 |
可用性公式
可用性 = MTBF / (MTBF + MTTR)

MTBF: 平均故障间隔时间
MTTR: 平均故障恢复时间

提高可用性:
1. 增加 MTBF:减少故障发生
2. 减少 MTTR:快速恢复

10.4 项目难点回答模板

1. 背景:遇到什么问题
2. 分析:问题原因是什么
3. 方案:尝试了哪些方案
4. 选择:为什么选择这个方案
5. 结果:最终效果如何
6. 反思:有什么收获

十一、高频面试题与答案

Q1: 如何介绍项目?

答案(STAR 法则):
1. Situation(背景):项目是什么,解决什么问题
2. Task(任务):你负责哪部分,目标是什么
3. Action(行动):你做了什么,用了什么技术
4. Result(结果):取得了什么成果,数据量化
示例: > 我负责订单系统的性能优化。当时系统 QPS 只有 500,大促期间频繁超时。 > 我通过引入 Redis 缓存热点数据、优化慢 SQL、增加读写分离, > 最终将 QPS 提升到 5000,接口 P99 从 800ms 降到 50ms。

Q2: 如何设计高并发系统?

答案
1. 缓存:Redis 缓存热点数据,减少数据库压力
2. 异步:消息队列削峰填谷,异步处理非核心逻辑
3. 分流:
   - CDN 静态资源加速
   - 负载均衡分散请求
   - 分库分表分散数据
4. 限流:保护系统不被压垮
5. 池化:连接池、线程池复用资源
6. 无状态:服务无状态,支持水平扩展

Q3: 如何保证高可用?

答案
策略
说明
冗余部署
多实例、多机房、主从复制
负载均衡
请求分发、故障节点摘除
熔断降级
服务不可用时快速失败
限流
保护系统不被压垮
超时重试
合理超时、有限重试
监控告警
及时发现问题
灰度发布
降低发布风险

Q4: 消息队列如何保证不丢失?

答案
生产端:
- 开启发送确认(confirm 模式)
- 失败重试 + 本地消息表

Broker 端:
- 消息持久化到磁盘
- 多副本同步(Kafka ISR)

消费端:
- 手动 ACK,处理完再确认
- 消费失败进入死信队列

Q5: 分布式事务怎么做?

答案
方案
原理
适用场景
2PC
协调者两阶段提交
强一致性,性能差
TCC
Try-Confirm-Cancel
高性能,实现复杂
Saga
事务补偿
长事务,最终一致
本地消息表
消息 + 定时任务
简单可靠
事务消息
RocketMQ 半消息
解耦,最终一致
推荐:优先考虑最终一致性方案(Saga、消息队列)

Q6: 分布式锁怎么实现?

答案
Redis 实现
# 加锁
SET lock_key unique_id NX PX 30000

# 解锁(Lua 脚本)
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
end
ZooKeeper 实现: - 创建临时顺序节点 - 监听前一个节点 - 最小序号获得锁
对比
Redis
ZooKeeper
性能
较低
可靠性
主从切换可能丢锁
高(CP)
实现
简单
复杂

Q7: 缓存一致性怎么保证?

答案
推荐方案:Cache Aside Pattern
读:先读缓存,没有则读数据库,写入缓存
写:先更新数据库,再删除缓存
为什么删除而不是更新? - 避免并发写导致数据不一致 - 懒加载,减少无效更新
延迟双删
1. 删除缓存
2. 更新数据库
3. 延迟 500ms 再删除缓存(防止并发读写不一致)

Q8: 接口幂等怎么做?

答案
方案
实现
适用场景
Token 机制
请求前获取 token,使用后失效
表单提交
唯一索引
数据库唯一约束
创建类操作
状态机
状态只能单向流转
订单状态变更
去重表
记录已处理请求
通用
乐观锁
version 字段控制
更新操作

Q9: 限流算法有哪些?

答案
算法
原理
特点
固定窗口
固定时间窗口计数
简单,有临界问题
滑动窗口
滑动时间窗口
平滑,实现复杂
漏桶
固定速率流出
平滑流量,无法应对突发
令牌桶
固定速率放入令牌
允许一定突发
推荐:令牌桶(Guava RateLimiter)或滑动窗口

Q10: 设计秒杀系统?

答案
1. 前端:
   - 静态资源 CDN
   - 按钮防重复点击
   - 答题/验证码削峰

2. 网关层:
   - 限流(令牌桶)
   - 黑名单过滤

3. 服务层:
   - Redis 预扣库存
   - 库存不足直接返回
   - 下单请求入消息队列

4. 数据层:
   - 异步消费创建订单
   - 数据库乐观锁扣减库存
关键点:尽量将请求拦截在上游,减少数据库压力

Q11: 设计短链服务?

答案
生成短链
1. 发号器生成唯一 ID
2. Base62 编码(0-9, a-z, A-Z3. 存储映射关系:短链 → 长链
访问流程
1. 用户访问短链
2. 服务查询映射关系
3. 302 重定向到长链
优化: - 布隆过滤器判断短链是否存在 - Redis 缓存热点短链 - 分库分表支持海量数据

Q12: 线上问题怎么排查?

答案
CPU 高
1. top -Hp <pid> 查看高 CPU 线程
2. printf "%x\n" <tid> 转换为十六进制
3. jstack <pid> | grep <tid> 查看线程堆栈
内存问题
1. jmap -heap <pid> 查看堆内存
2. jmap -dump:format=b,file=heap.hprof <pid>
3. MAT 分析堆转储
GC 问题
1. jstat -gc <pid> 1000 查看 GC 情况
2. 分析 GC 日志
3. 调整堆大小、GC 算法

最后更新:2026-01-09
你觉得这篇文章怎么样?
YYDS
比心
加油
菜狗
views

Loading Comments...