Files
interview/questions/09-网络与安全/性能优化.md
yasinshaw 0e46a367c4 refactor: rename files to Chinese and organize by category
Organized 50 interview questions into 12 categories:
- 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc.
- 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理
- 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc.
- 04-消息队列 (1 file): RocketMQ/Kafka
- 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc.
- 06-JVM (1 file): JVM和垃圾回收
- 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc.
- 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮
- 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化
- 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx
- 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性
- 12-面试技巧 (1 file): 面试技巧和职业规划

All files renamed to Chinese for better accessibility and
organized into categorized folders for easier navigation.

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:10:53 +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
  • 能根据业务特点制定性能指标