Files
interview/questions/performance-tuning.md
yasinshaw fe2e6dc2f2 feat: add 50 backend interview questions and answers
Generated comprehensive interview preparation materials covering:
- Distributed systems (transactions, locks, ID generation, consistency)
- Database (indexing, sharding, replication, transactions)
- Caching (Redis, cache problems, distributed lock)
- Message queues (RocketMQ, Kafka)
- Concurrency (ThreadLocal, ConcurrentHashMap, thread pools)
- JVM (GC, memory, tuning)
- System design (seckill, short URL, IM, feed, LBS)
- Algorithms (B+ tree, LRU, Red-Black tree, Skip list, Timing wheel)
- Network (TCP/IP, HTTP/HTTPS)
- Security (encryption, SQL injection, XSS)
- Performance tuning
- Design patterns
- Microservices (Spring Boot, Gateway, Service Mesh)
- Container orchestration (Kubernetes, Docker)
- CI/CD, observability

Each file includes:
- Detailed questions
- Comprehensive answers
- Code examples
- Real project experience
- Alibaba P7 level requirements

Generated with [Claude Code](https://claude.com/claude-code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-01 00:09:50 +08:00

11 KiB
Raw Blame History

性能优化

问题

  1. 性能优化的常见思路和方法有哪些?
  2. 如何进行系统性能瓶颈分析?
  3. 数据库性能优化有哪些方法?
  4. JVM 性能调优的常见问题和解决方案?
  5. 接口性能优化有哪些技巧?
  6. 如何进行全链路压测?
  7. 在实际项目中如何进行性能优化?

标准答案

1. 性能优化思路

优化原则

  1. 测量优先:先测量,后优化
  2. 抓大放小:优化瓶颈,而非所有地方
  3. 数据驱动:用数据说话
  4. 权衡取舍:优化往往带来复杂性

优化层次

用户响应时间
    ↓
前端优化减少请求、CDN、缓存
    ↓
网络优化(减少 RTT、压缩
    ↓
后端优化(代码、算法、并发)
    ↓
数据库优化(索引、分库分表)
    ↓
操作系统优化TCP、内核参数
    ↓
硬件优化CPU、内存、磁盘、网络

2. 性能瓶颈分析

分析工具

1. CPU 分析

# top 命令
top -p <pid>

# 查看 CPU 使用率
%CPU: 80.5

# 查看线程 CPU
top -H -p <pid>

2. 内存分析

# 查看内存使用
free -h

# 查看进程内存
ps aux | grep java

# JVM 堆内存
jmap -heap <pid>

3. 磁盘 I/O

# iostat
iostat -x 1

# 查看 I/O 等待
%iowait: 15.2  # 高说明磁盘瓶颈

4. 网络 I/O

# 查看网络连接
netstat -anp | grep <pid>

# 查看网络流量
iftop

Java 性能分析工具

1. JProfiler

  • CPU Profiler
  • Memory Profiler
  • Thread Profiler

2. Arthas阿里开源

# 安装
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

# 查看 CPU 最高的线程
dashboard

# 查看方法调用耗时
trace com.example.UserService getUser

# 查看类加载
sc -d com.example.User

3. VisualVM

  • JDK 自带
  • 可视化界面

3. 数据库性能优化

优化层次

SQL 优化
    ↓
索引优化
    ↓
表结构优化
    ↓
数据库配置优化
    ↓
架构优化(读写分离、分库分表)

SQL 优化

1. 避免 SELECT *

-- ❌ 查询所有列
SELECT * FROM users WHERE id = 1;

-- ✅ 只查询需要的列
SELECT id, name, email FROM users WHERE id = 1;

2. 避免 IN 子查询

-- ❌ 子查询
SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE status = 1);

-- ✅ JOIN
SELECT o.* FROM orders o
INNER JOIN users u ON o.user_id = u.id
WHERE u.status = 1;

3. 批量操作

-- ❌ 单条插入
INSERT INTO orders (id, user_id) VALUES (1, 100);
INSERT INTO orders (id, user_id) VALUES (2, 100);
INSERT INTO orders (id, user_id) VALUES (3, 100);

-- ✅ 批量插入
INSERT INTO orders (id, user_id) VALUES
(1, 100),
(2, 100),
(3, 100);

4. 使用 UNION ALL 代替 UNION

-- ❌ UNION去重
SELECT name FROM users_a
UNION
SELECT name FROM users_b;

-- ✅ UNION ALL不去重
SELECT name FROM users_a
UNION ALL
SELECT name FROM users_b;

索引优化

1. 创建合适的索引

-- 为查询条件创建索引
CREATE INDEX idx_user_id ON orders(user_id);

-- 为排序创建索引
CREATE INDEX idx_created_at ON orders(created_at);

-- 联合索引(注意最左前缀)
CREATE INDEX idx_user_status ON orders(user_id, status);

2. 避免索引失效

-- ❌ 使用函数
SELECT * FROM orders WHERE YEAR(created_at) = 2024;

-- ✅ 范围查询
SELECT * FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01';

-- ❌ 隐式转换
SELECT * FROM users WHERE phone = 13800138000;  -- phone 是 VARCHAR

-- ✅ 显式转换
SELECT * FROM users WHERE phone = '13800138000';

-- ❌ 前缀模糊查询
SELECT * FROM users WHERE name LIKE '%张';

-- ✅ 后缀模糊查询
SELECT * FROM users WHERE name LIKE '张%';

表结构优化

1. 垂直拆分

-- 拆分前(大表)
CREATE TABLE users (
  id BIGINT PRIMARY KEY,
  name VARCHAR(50),
  email VARCHAR(100),
  password VARCHAR(100),
  intro TEXT,           -- 简介(可能很长)
  settings JSON,        -- 设置
  created_at DATETIME
);

-- 拆分后
CREATE TABLE users_base (
  id BIGINT PRIMARY KEY,
  name VARCHAR(50),
  email VARCHAR(100),
  password VARCHAR(100),
  created_at DATETIME
);

CREATE TABLE users_ext (
  user_id BIGINT PRIMARY KEY,
  intro TEXT,
  settings JSON
);

2. 水平拆分

-- 拆分前(单表数据量大)
CREATE TABLE orders (
  id BIGINT PRIMARY KEY,
  user_id BIGINT,
  amount DECIMAL(10,2),
  created_at DATETIME
);  -- 1 亿条数据

-- 拆分后(按时间分表)
CREATE TABLE orders_2024_01 (
  id BIGINT PRIMARY KEY,
  user_id BIGINT,
  amount DECIMAL(10,2),
  created_at DATETIME
);

CREATE TABLE orders_2024_02 (
  ...
);

4. JVM 性能调优

常见问题

1. 内存泄漏

// ❌ 内存泄漏
public class Cache {
    private static final Map<String, Object> cache = new HashMap<>();

    public void put(String key, Object value) {
        cache.put(key, value);  // 永不清理,内存泄漏
    }
}

// ✅ 使用 Guava Cache
public class Cache {
    private static final Cache<String, Object> cache = CacheBuilder.newBuilder()
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .maximumSize(10000)
        .build();

    public void put(String key, Object value) {
        cache.put(key, value);
    }
}

2. 频繁 GC

# 查看 GC 情况
jstat -gcutil <pid> 1000

# 输出
  S0     S1     E      O       M     CCS    YGC     YGCT     FGC    FGCT     GCT
  0.00  70.15  80.23  65.40  95.12  90.23   1523    45.236     10    12.345   57.581

# YGC年轻代 GC 次数(正常 1000 次/小时以下)
# FGC老年代 GC 次数(应该接近 0
# GCT总 GC 时间(应该 < 5%

调优

# 调整堆内存大小
-Xms4g -Xmx4g

# 调整年轻代大小
-Xmn2g

# 使用 G1 收集器(大堆内存推荐)
-XX:+UseG1GC

# 调整 GC 并行线程
-XX:ParallelGCThreads=8

3. CPU 100%

# 查看最耗 CPU 的线程
top -H -p <pid>

# 转换线程 ID 为 16 进制
printf "%x" <tid>

# 查看线程堆栈
jstack <pid> | grep <tid-in-hex> -A 20

5. 接口性能优化

优化技巧

1. 异步处理

// ❌ 同步处理(慢)
@PostMapping("/order")
public String createOrder(@RequestBody Order order) {
    // 1. 保存订单100ms
    orderService.save(order);

    // 2. 发送邮件500ms
    emailService.send(order);

    // 3. 发送短信300ms
    smsService.send(order);

    // 总耗时900ms
    return "success";
}

// ✅ 异步处理(快)
@PostMapping("/order")
public String createOrder(@RequestBody Order order) {
    // 1. 保存订单100ms
    orderService.save(order);

    // 2. 异步发送邮件、短信
    CompletableFuture.runAsync(() -> {
        emailService.send(order);
        smsService.send(order);
    });

    // 总耗时100ms
    return "success";
}

2. 缓存

// ❌ 每次查询数据库
public User getUser(Long userId) {
    return userMapper.selectById(userId);  // 50ms
}

// ✅ 使用缓存
@Cacheable(value = "users", key = "#userId")
public User getUser(Long userId) {
    return userMapper.selectById(userId);  // 第一次 50ms后续 1ms
}

3. 批量查询

// ❌ 循环查询N+1 问题)
List<Order> orders = orderMapper.selectList();
for (Order order : orders) {
    User user = userMapper.selectById(order.getUserId());  // N 次查询
    order.setUser(user);
}

// ✅ 批量查询
List<Order> orders = orderMapper.selectList();
Set<Long> userIds = orders.stream()
    .map(Order::getUserId)
    .collect(Collectors.toSet());
Map<Long, User> userMap = userMapper.selectByIds(userIds);  // 1 次查询
orders.forEach(o -> o.setUser(userMap.get(o.getUserId())));

4. 连接池优化

# HikariCP 配置
spring:
  datasource:
    hikari:
      minimum-idle: 10           # 最小空闲连接
      maximum-pool-size: 50      # 最大连接池大小
      connection-timeout: 30000  # 连接超时时间
      idle-timeout: 600000       # 空闲连接超时
      max-lifetime: 1800000      # 连接最大生命周期

6. 全链路压测

压测工具

1. JMeter

  • 图形化界面
  • 支持分布式压测
  • 可录制脚本

2. LocustPython

from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 3)

    @task
    def index(self):
        self.client.get("/")

    @task(3)
    def api(self):
        self.client.get("/api/users")

运行

locust -f locustfile.py --host=https://example.com

压测流程

1. 制定压测计划
   - 确定目标QPS、响应时间
   - 确定场景(秒杀、日常流量)

2. 编写压测脚本
   - 模拟真实用户行为
   - 准备测试数据

3. 执行压测
   - 逐步加压
   - 记录指标

4. 分析结果
   - 找出瓶颈
   - 优化后再次压测

5. 容量评估
   - 确定系统容量
   - 预留缓冲(如 30%

压测指标

指标 说明 目标值
QPS 每秒请求数 根据业务需求
响应时间 P99 < 200ms 根据业务需求
错误率 错误请求比例 < 0.1%
CPU 使用率 CPU 占用 < 70%
内存使用率 内存占用 < 80%
TPS 每秒事务数 根据业务需求

7. 实际项目案例

案例 1接口响应时间从 2s 优化到 100ms

问题

  • 用户列表接口响应时间 2 秒
  • 数据库查询慢

分析

EXPLAIN SELECT * FROM users WHERE status = 1;
-- type: ALL全表扫描
-- rows: 1000000

优化

-- 1. 添加索引
CREATE INDEX idx_status ON users(status);

-- 2. 只查询需要的字段
SELECT id, name, email FROM users WHERE status = 1;

-- 3. 添加缓存
@Cacheable("users")

结果:响应时间降至 100ms


案例 2解决频繁 GC 问题

问题

  • 应用频繁 Full GC
  • CPU 使用率 100%

分析

# 查看 GC 日志
jstat -gcutil <pid> 1000

# FGC 频繁,说明老年代内存不足

优化

# 调整 JVM 参数
-Xms8g -Xmx8g              # 增加堆内存
-Xmn4g                     # 调整年轻代大小
-XX:+UseG1GC               # 使用 G1 收集器
-XX:MaxGCPauseMillis=200   # 设置最大 GC 暂停时间

结果Full GC 次数从每小时 10 次降至 0 次


8. 阿里 P7 加分项

深度理解

  • 理解性能优化的底层原理(操作系统、网络、数据库)
  • 理解各种性能分析工具的实现原理
  • 理解性能测试的统计学方法

实战经验

  • 有将接口从秒级优化到毫秒级的经验
  • 有解决线上性能问题的经验
  • 有全链路压测的经验

架构能力

  • 能设计高性能架构
  • 能设计性能监控体系
  • 能制定性能优化规范

技术选型

  • 了解各种性能分析工具JProfiler、Arthas、SkyWalking
  • 了解分布式追踪系统Zipkin、Jaeger
  • 能根据业务特点制定性能指标