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>
This commit is contained in:
yasinshaw
2026-03-01 00:10:53 +08:00
parent fe2e6dc2f2
commit 0e46a367c4
47 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
# API 网关核心原理
## 问题
1. 什么是 API 网关?为什么需要 API 网关?
2. API 网关的核心功能有哪些?
3. Spring Cloud Gateway 和 Zuul 的区别?
4. 网关的限流、熔断、降级如何实现?
5. 网关的路由和负载均衡策略?
---
## 标准答案
### 1. API 网关的作用
**核心功能**
1. **路由转发**:将请求转发到后端服务
2. **统一鉴权**:集中的认证和授权
3. **限流熔断**:保护后端服务
4. **日志监控**:统一的日志和监控
5. **协议转换**HTTP → WebSocket、gRPC 等
6. **灰度发布**:按规则路由流量
---
### 2. Spring Cloud Gateway 核心概念
**三大组件**
```
Route路由
Predicate断言
Filter过滤器
```
**示例**
```yaml
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
- Header=Authorization, .*
filters:
- StripPrefix=1
- RequestRateLimiter=10 # 限流10 QPS
```
---
### 3. Gateway vs Zuul
| 特性 | Zuul 1.x | Zuul 2.x | Spring Cloud Gateway |
|------|----------|----------|---------------------|
| **模型** | Servlet 阻塞 | Netty 非阻塞 | Netty 非阻塞 |
| **性能** | 低 | 中 | 高 |
| **Spring** | 集成好 | 集成一般 | 原生支持 |
| **动态路由** | 不支持 | 支持 | 支持 |
| **限流** | 需自研 | 需自研 | 内置Redis |
---
### 4. 核心功能实现
#### **限流**
```yaml
spring:
cloud:
gateway:
routes:
- id: rate-limiter
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒填充 10 个令牌
redis-rate-limiter.burstCapacity: 20 # 桶容量 20
```
---
#### **熔断Circuit Breaker**
```yaml
spring:
cloud:
gateway:
routes:
- id: circuit-breaker
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- name: CircuitBreaker
args:
fallbackUri: forward:/fallback
```
---
#### **统一鉴权**
```java
@Component
public class AuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token == null || !validateToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
```
---
### 5. 网关高可用
**部署架构**
```
┌─────────────┐
│ 负载均衡 │
│ (Nginx) │
└──────┬──────┘
┌───────────────┼───────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Gateway 1│ │Gateway 2│ │Gateway 3│
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└──────────────┼──────────────┘
┌──────────────┼──────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Service A│ │Service B│ │Service C│
└─────────┘ └─────────┘ └─────────┘
```
---
### 6. 阿里 P7 加分项
**深度理解**
- 理解 WebFlux 的响应式编程模型
- 理解 Netty 的事件循环
- 理解限流算法(令牌桶、漏桶)
**实战经验**
- 有网关性能调优的经验
- 有网关灰度发布的经验
- 有网关监控和故障排查的经验
**架构能力**
- 能设计高可用网关架构
- 能设计网关的监控体系
- 能设计网关的动态路由方案

View File

@@ -0,0 +1,379 @@
# LBS 附近的人系统设计
## 需求分析和数据量评估
### 需求分析
- **核心功能**:位置搜索、附近的人、距离计算、实时更新
- **业务场景**:社交软件、外卖服务、打车应用
- **QPS评估**日查询10亿次峰值QPS 5万+
- **数据规模**用户1亿+日均位置更新1000万+
### 数据量评估
- **用户位置表**1亿条实时更新频率高
- **位置历史表**100亿+条,存储轨迹信息
- **地理索引表**:全球空间索引,数据量大
- **社交关系表**10亿+条,好友关系数据
## 核心技术难点
### 1. 海量数据处理
- 亿级用户位置数据存储
- 实时数据写入性能要求
- 空间索引构建和维护
### 2. 实时性要求
- 位置信息实时更新
- 查询响应毫秒级
- 数据一致性问题
### 3. 距离计算优化
- 快速计算两点间距离
- 批量距离计算优化
- 空间索引查询优化
### 4. 隐私保护
- 用户位置隐私
- 数据脱敏处理
- 访问权限控制
## 系统架构设计
### 总体架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 移动端APP │ │ Web管理后台 │ │ 第三方API │
│ (iOS/Android)│ │ (PC) │ │ (SDK) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ API网关 │ │ 负载均衡 │ │ CDN加速 │
│ (Gateway) │ │ (Nginx) │ │ (Edge) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 位置服务 │ │ 搜索服务 │ │ 计算服务 │
│ (微服务) │ │ (微服务) │ │ (微服务) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└─────────────────────┼───────────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Redis集群 │ │ 数据库集群 │ │ 消息队列 │
│ (缓存+pub/sub)│ │ (PostGIS) │ │ (Kafka/RabbitMQ)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 地理计算 │ │ 数据仓库 │ │ 地图渲染 │
│ (Geospatial) │ │ (ClickHouse) │ │ (Mapbox) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 关键组件
#### 1. 流量层
- **API网关**:请求路由、限流、认证
- **负载均衡**Nginx L7负载均衡
- **CDN加速**:静态资源缓存
#### 2. 服务层
- **位置服务**:位置更新、订阅管理
- **搜索服务**:附近的人查询
- **计算服务**:距离计算、路线规划
- **社交服务**:好友关系管理
#### 3. 存储层
- **Redis集群**:位置缓存、订阅频道
- **PostgreSQL**:空间数据存储
- **ClickHouse**:地理位置分析
- **MongoDB**:轨迹数据存储
#### 4. 分析层
- **数据仓库**:离线数据分析
- **实时计算**Flink/Kafka Streams
- **地图服务**:地图渲染和展示
## 数据库设计
### 用户位置表
```sql
CREATE TABLE `user_location` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`latitude` decimal(10,8) NOT NULL COMMENT '纬度',
`longitude` decimal(11,8) NOT NULL COMMENT '经度',
`accuracy` decimal(10,2) DEFAULT NULL COMMENT '定位精度(米)',
`device_type` varchar(20) DEFAULT NULL COMMENT '设备类型',
`app_version` varchar(50) DEFAULT NULL COMMENT '应用版本',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`expire_at` timestamp NOT NULL COMMENT '过期时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_id` (`user_id`),
KEY `idx_location` (`latitude`, `longitude`),
KEY `idx_expire_at` (`expire_at`),
SPATIAL KEY `idx_spatial` (`latitude`, `longitude`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 位置历史表
```sql
CREATE TABLE `location_history` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`latitude` decimal(10,8) NOT NULL COMMENT '纬度',
`longitude` decimal(11,8) NOT NULL COMMENT '经度',
`accuracy` decimal(10,2) DEFAULT NULL COMMENT '定位精度(米)',
`timestamp` datetime NOT NULL COMMENT '时间戳',
`device_type` varchar(20) DEFAULT NULL COMMENT '设备类型',
PRIMARY KEY (`id`),
KEY `idx_user_timestamp` (`user_id`, `timestamp`),
KEY `idx_location` (`latitude`, `longitude`),
SPATIAL KEY `idx_spatial` (`latitude`, `longitude`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 地理索引表
```sql
CREATE TABLE `geo_index` (
`id` bigint NOT NULL AUTO_INCREMENT,
`grid_id` varchar(20) NOT NULL COMMENT '网格ID',
`min_lat` decimal(10,8) NOT NULL COMMENT '最小纬度',
`max_lat` decimal(10,8) NOT NULL COMMENT '最大纬度',
`min_lng` decimal(11,8) NOT NULL COMMENT '最小经度',
`max_lng` decimal(11,8) NOT NULL COMMENT '最大经度',
`user_count` int NOT NULL DEFAULT 0 COMMENT '用户数量',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_grid_id` (`grid_id`),
KEY `idx_bounds` (`min_lat`, `max_lat`, `min_lng`, `max_lng`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 好友关系表
```sql
CREATE TABLE `user_friends` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`friend_id` bigint NOT NULL COMMENT '好友ID',
`distance` decimal(10,2) DEFAULT NULL COMMENT '距离(公里)',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_friend` (`user_id`, `friend_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_friend_id` (`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
## 缓存策略
### Redis缓存设计
```typescript
// 用户位置缓存
const USER_LOCATION_PREFIX = 'location:';
const USER_LOCATION_TTL = 60; // 1分钟
// 地理网格缓存
const GRID_PREFIX = 'grid:';
const GRID_TTL = 300; // 5分钟
// 用户订阅缓存
const SUBSCRIPTION_PREFIX = 'subscription:';
const SUBSCRIPTION_TTL = 3600; // 1小时
// 距离计算缓存
const DISTANCE_PREFIX = 'distance:';
const DISTANCE_TTL = 60; // 1分钟
```
### 缓存策略
1. **多级缓存**
- 本地缓存Caffeine
- 分布式缓存Redis Cluster
- CDN缓存静态资源
2. **缓存更新策略**
- Write Behind异步更新
- Refresh Ahead预加载热点数据
- Cache Invalidation定时失效
3. **空间索引缓存**
- 网格索引预加载
- 热点区域缓存
- 分层缓存策略
### GeoHash实现
```python
import math
def geohash_encode(latitude, longitude, precision=12):
# 地球半径(米)
earth_radius = 6371000
# GeoHash字符集
chars = "0123456789bcdefghjkmnpqrstuvwxyz"
# 计算精度对应的网格大小
grid_size = 5e6 / (2 ** (precision / 2))
# 计算经纬度范围
lat_min = -90
lat_max = 90
lng_min = -180
lng_max = 180
geo_hash = []
for i in range(precision):
# 纬度二进制
mid_lat = (lat_min + lat_max) / 2
if latitude >= mid_lat:
lat_min = mid_lat
lat_bit = 1
else:
lat_max = mid_lat
lat_bit = 0
# 经度二进制
mid_lng = (lng_min + lng_max) / 2
if longitude >= mid_lng:
lng_min = mid_lng
lng_bit = 1
else:
lng_max = mid_lng
lng_bit = 0
# 组合成字符索引
index = lat_bit * 2 + lng_bit
geo_hash.append(chars[index])
return ''.join(geo_hash)
def calculate_distance(lat1, lng1, lat2, lng2):
# Haversine公式计算距离
R = 6371000 # 地球半径(米)
dLat = math.radians(lat2 - lat1)
dLng = math.radians(lng2 - lng1)
a = (math.sin(dLat/2) * math.sin(dLat/2) +
math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
math.sin(dLng/2) * math.sin(dLng/2))
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
distance = R * c
return distance
```
## 扩展性考虑
### 1. 水平扩展
- **无状态服务**:位置服务和搜索服务无状态化
- **数据分片**按用户ID分片
- **读写分离**:主库写入,从库读取
### 2. 垂直扩展
- **服务拆分**:位置更新服务、查询服务、计算服务
- **数据分层**:热数据、温数据、冷数据
- **多级缓存**本地、Redis、CDN
### 3. 全球化部署
- **地域化服务**:按地域部署服务
- **数据同步**:跨地域数据同步
- **灾备切换**:多机房容灾
### 4. 性能优化
- **空间索引**R-Tree、Quadtree
- **批量处理**:批量查询优化
- **异步处理**:消息队列异步化
## 实际项目经验
### 1. 技术栈选择
- **前端**React Native + Flutter
- **后端**Spring Boot + Node.js
- **数据库**PostgreSQL + Redis
- **缓存**Redis Cluster
- **消息队列**Kafka
- **监控**Prometheus + Grafana
### 2. 性能优化
- **空间索引优化**GeoHash、R-Tree
- **缓存优化**:多级缓存策略
- **数据库优化**:分库分表、索引优化
- **网络优化**HTTP/2、Keep-Alive
### 3. 运维部署
- **容器化**Docker + Kubernetes
- **CI/CD**Jenkins + GitLab
- **监控告警**ELK Stack + AlertManager
- **压测**JMeter + Locust
### 4. 安全设计
- **位置隐私**:数据脱敏、权限控制
- **数据加密**:传输加密、存储加密
- **访问控制**API鉴权、黑白名单
## 阿里P7加分项
### 1. 架构设计能力
- **高可用架构**99.99%可用性
- **高性能架构**:支持亿级查询
- **全球化架构**:全球多机房部署
### 2. 技术深度
- **空间算法**GeoHash、R-Tree算法
- **分布式系统**:分布式缓存、分布式计算
- **数据库优化**PostGIS优化、空间索引
### 3. 业务理解
- **社交业务**:理解社交应用场景
- **位置服务**掌握LBS业务模式
- **用户行为**:分析用户移动模式
### 4. 团队管理
- **技术团队**带领20人+团队
- **项目管控**:管理千万级用户项目
- **技术方案**:主导技术架构设计
### 5. 前沿技术
- **边缘计算**:边缘节点处理
- **AI应用**:轨迹预测、位置推荐
- **Serverless**:函数化服务
## 面试常见问题
### 1. 如何高效查询附近的人?
- **空间索引**GeoHash、R-Tree
- **网格划分**:地理网格索引
- **缓存策略**:多级缓存优化
### 2. 如何保证位置数据实时性?
- **推送机制**WebSocket实时推送
- **订阅模式**:用户订阅位置变化
- **数据过期**:定时清理过期数据
### 3. 如何处理海量位置数据?
- **分库分表**按用户ID分片
- **数据归档**:冷热数据分离
- **压缩存储**:轨迹数据压缩
### 4. 如何保护用户隐私?
- **数据脱敏**:位置信息模糊化
- **权限控制**:基于关系的访问控制
- **加密存储**:敏感信息加密
### 5. 如何优化距离计算?
- **近似计算**GeoHash过滤
- **批量计算**:向量运算优化
- **缓存机制**:距离结果缓存

View File

@@ -0,0 +1,745 @@
# RPC 框架
## 问题
**背景**在分布式系统中服务间通信需要高效、可靠的远程调用机制。RPCRemote Procedure Call框架屏蔽了网络通信的复杂性使远程调用像本地调用一样简单。
**问题**
1. 什么是 RPC它和 HTTP REST 有什么区别?
2. Dubbo 的核心架构和工作原理是什么?
3. gRPC 的优势是什么?它如何实现高性能?
4. 请描述 Dubbo 的负载均衡策略
5. Dubbo 的服务注册与发现机制是怎样的?
6. RPC 框架如何实现序列化?常见的序列化协议有哪些?
7. 在实际项目中如何选择 RPC 框架?
8. RPC 框架如何处理超时、重试和熔断?
---
## 标准答案
### 1. RPC vs HTTP REST
#### **RPC 定义**
远程过程调用Remote Procedure Call是一种计算机通信协议允许运行在一台计算机的程序调用另一台计算机的子程序而开发者无需额外编码这种交互。
#### **对比表**
| 特性 | RPC (Dubbo/gRPC) | HTTP REST |
|------|------------------|-----------|
| 传输协议 | TCP (长连接) | HTTP/1.1 (短连接) / HTTP/2 |
| 序列化 | 二进制Hessian/Protobuf | JSON/XML |
| 性能 | 高(紧凑、高效) | 中(文本解析开销) |
| 易用性 | 需要接口定义 | 无需定义,浏览器直接访问 |
| 耦合度 | 强耦合(需要 stub 代码) | 松耦合 |
| 流量管理 | 需要网关 | 天然支持Nginx等 |
| 适用场景 | 内部微服务通信 | 对外 API、跨语言调用 |
#### **代码对比**
**RPC 调用Dubbo**
```java
// 服务提供者
public interface UserService {
User getUserById(Long id);
}
// 服务消费者
// 像调用本地方法一样调用远程服务
@Reference
private UserService userService;
public void process() {
User user = userService.getUserById(1L);
}
```
**HTTP REST 调用**
```java
// 服务提供者
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id);
}
}
// 服务消费者
RestTemplate restTemplate = new RestTemplate();
public void process() {
String url = "http://user-service/api/users/1";
User user = restTemplate.getForObject(url, User.class);
}
```
---
### 2. Dubbo 核心架构
#### **架构图**
```
┌─────────────────┐
│ Registry │
│ (注册中心) │
│ Zookeeper/Nacos│
└─────────────────┘
▲ ▲
│ │
Register │ │ Subscribe
(注册) │ │ (订阅)
│ │
┌──────────────────────┴───┴──────────────────────┐
│ │
│ Provider Consumer │
│ ┌──────────┐ ┌──────────┐│
│ │Protocol │ │Protocol ││
│ │ (协议层) │ │ (协议层) ││
│ └──────────┘ └──────────┘│
│ ┌──────────┐ ┌──────────┐│
│ │ Cluster │◄──────────────────►│ Cluster ││
│ │ (集群层) │ Directory │ (集群层) ││
│ └──────────┘ └──────────┘│
│ ┌──────────┐ ┌──────────┐│
│ │ Proxy │ │ Proxy ││
│ │ (代理层) │ │ (代理层) ││
│ └──────────┘ └──────────┘│
│ ┌──────────┐ ┌──────────┐│
│ │ Service │ │ Service ││
│ │ (服务层) │ │ (服务层) ││
│ └──────────┘ └──────────┘│
└─────────────────────────────────────────────┘
│ Invoke
│ (调用)
┌──────────┐
│ Channel │
│ (网络层) │
└──────────┘
│ Exchange
│ (数据交换)
┌──────────┐
│ Serialize│
│ (序列化) │
└──────────┘
```
#### **核心角色**
**1. Container服务容器**
- 负责启动、加载和运行服务提供者
- 通常是 Spring 容器
**2. Provider服务提供者**
- 暴露服务的应用
- 启动时向注册中心注册服务
**3. Consumer服务消费者**
- 调用远程服务的应用
- 启动时向注册中心订阅服务
**4. Registry注册中心**
- 服务注册与发现
- 常见实现Zookeeper、Nacos、Redis
**5. Monitor监控中心**
- 统计服务调用次数和调用时间
- 常见实现Dubbo Admin、Prometheus
#### **代码示例**
**服务提供者配置**
```xml
<!-- provider.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息 -->
<dubbo:application name="user-provider"/>
<!-- 使用 Zookeeper 注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 使用 dubbo 协议暴露服务 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.example.UserService"
ref="userService" version="1.0.0"/>
<!-- 服务实现 -->
<bean id="userService" class="com.example.UserServiceImpl"/>
</beans>
```
**服务消费者配置**
```xml
<!-- consumer.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 消费方应用信息 -->
<dubbo:application name="user-consumer"/>
<!-- 使用 Zookeeper 注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 生成远程服务代理 -->
<dubbo:reference id="userService"
interface="com.example.UserService"
version="1.0.0"
timeout="3000"
retries="2"/>
</beans>
```
---
### 3. gRPC 高性能原理
#### **核心特性**
**1. HTTP/2 多路复用**
```
HTTP/1.1:
Request 1 ──► TCP Connection 1 ──► Response 1
Request 2 ──► TCP Connection 2 ──► Response 2
Request 3 ──► TCP Connection 3 ──► Response 3
HTTP/2:
Request 1 ──┐
Request 2 ──┼─► TCP Connection ──► Response 1
Request 3 ──┘ Response 2
Response 3
```
**2. Protobuf 二进制序列化**
```protobuf
// user.proto
syntax = "proto3";
package user;
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
}
message User {
int64 id = 1;
string name = 2;
string email = 3;
}
message GetUserRequest {
int64 id = 1;
}
message ListUsersRequest {
int32 page = 1;
int32 size = 2;
}
message ListUsersResponse {
repeated User users = 1;
int32 total = 2;
}
```
**性能对比**
```
JSON: {"id":1,"name":"Alice","email":"alice@example.com"}
└─ 56 字节
Protobuf: [0x08 0x01 0x12 0x05 0x41 0x6C 0x69 0x63 0x65 ...]
└─ ~20 字节(压缩 60%+
```
**3. 流式传输**
```python
# 服务端流式 RPC
async def ListUsers(request, context):
for user in database.iter_users():
yield user # 持续发送,无需等待全部数据
# 客户端流式 RPC
async def UploadUsers(request_iterator, context):
for user_request in request_iterator:
database.save(user_request.user)
return UploadStatus(success=True)
# 双向流式 RPC
async def Chat(request_iterator, context):
async for msg in request_iterator:
response = process_message(msg)
yield response
```
#### **代码示例Python**
**服务端**
```python
import grpc
from concurrent import futures
import user_pb2
import user_pb2_grpc
class UserServiceImpl(user_pb2_grpc.UserServiceServicer):
def GetUser(self, request, context):
# 查询数据库
user = db.query(User).filter_by(id=request.id).first()
return user_pb2.User(
id=user.id,
name=user.name,
email=user.email
)
def ListUsers(self, request, context):
# 服务端流式响应
users = db.query(User).limit(request.size).offset(request.page * request.size)
for user in users:
yield user_pb2.User(id=user.id, name=user.name, email=user.email)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
user_pb2_grpc.add_UserServiceServicer_to_server(UserServiceImpl(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
```
**客户端**
```python
import grpc
import user_pb2
import user_pb2_grpc
def run():
with grpc.insecure_channel('localhost:50051') as channel:
stub = user_pb2_grpc.UserServiceStub(channel)
# 简单 RPC
response = stub.GetUser(user_pb2.GetUserRequest(id=1))
print(f"User: {response.name}")
# 服务端流式 RPC
for user in stub.ListUsers(user_pb2.ListUsersRequest(page=0, size=10)):
print(f"User: {user.name}")
if __name__ == '__main__':
run()
```
---
### 4. Dubbo 负载均衡策略
#### **策略对比**
| 策略 | 说明 | 适用场景 |
|------|------|----------|
| Random随机 | 随机选择 provider | 性能相近的实例 |
| RoundRobin轮询 | 按权重轮询 | 性能有差异的实例 |
| LeastActive最少活跃 | 优先调用活跃数少的 | 性能差异大 |
| ConsistentHash一致性哈希 | 相同参数路由到同一 provider | 有状态服务 |
| ShortestResponse最短响应 | 优先选择响应时间短的 | 对延迟敏感 |
#### **代码示例**
**配置负载均衡**
```xml
<dubbo:reference id="userService"
interface="com.example.UserService"
loadbalance="roundRobin" <!-- -->
timeout="3000"/>
```
**自定义负载均衡**
```java
public class CustomLoadBalance extends AbstractLoadBalance {
@Override
protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
// 自定义负载均衡逻辑
// 例如:基于地理位置的负载均衡
String location = getUserLocation();
return invokers.stream()
.filter(invoker -> invoker.getUrl().getParameter("location").equals(location))
.findFirst()
.orElse(invokers.get(0));
}
}
// 注册自定义负载均衡
SPI.register(CustomLoadBalance.class);
```
#### **LeastActive 原理**
```
Provider A: Active = 5 (正在处理 5 个请求)
Provider B: Active = 2 (正在处理 2 个请求)
Provider C: Active = 8 (正在处理 8 个请求)
选择顺序B > A > C
原因B 的负载最轻,应该优先分配
```
---
### 5. 服务注册与发现
#### **Zookeeper 实现**
**目录结构**
```
/dubbo
└─ com.example.UserService
├─ providers
│ ├─ dubbo://192.168.1.10:20880/...?version=1.0.0
│ ├─ dubbo://192.168.1.11:20880/...?version=1.0.0
│ └─ dubbo://192.168.1.12:20880/...?version=1.0.0
└─ consumers
└─ consumer://192.168.1.20/...?version=1.0.0
```
**工作流程**
```
1. Provider 启动
2. 创建临时节点 /dubbo/.../providers/dubbo://ip:port/...
3. Consumer 启动
4. 订阅 /dubbo/.../providers/ 节点
5. 获取 provider 列表
6. 监听 provider 变化(新增/下线)
7. 动态更新本地缓存
```
#### **代码示例Zookeeper**
```java
// 注册中心配置
RegistryConfig registry = new RegistryConfig();
registry.setAddress("zookeeper://127.0.0.1:2181");
registry.setTimeout(5000);
// 或者使用 Nacos
RegistryConfig registry = new RegistryConfig();
registry.setAddress("nacos://127.0.0.1:8848");
```
#### **服务健康检查**
```java
// Dubbo 心跳机制
public class HeartbeatTask implements Runnable {
@Override
public void run() {
// 每隔 5 秒发送心跳
channel.send heartbeat();
}
}
// Zookeeper 临时节点特性
// - Provider 断开连接后,临时节点自动删除
// - Consumer 立即感知到下线,剔除该 provider
```
---
### 6. 序列化协议对比
#### **常见序列化协议**
| 协议 | 优点 | 缺点 | 适用场景 |
|------|------|------|----------|
| Hessian | 简单、高效 | 不支持跨语言 | Dubbo 默认 |
| Protobuf | 高性能、跨语言 | 需要定义 .proto | gRPC |
| JSON | 易读、跨语言 | 冗长、解析慢 | HTTP REST |
| Kryo | 高性能 | 不支持跨语言 | Dubbo |
| Avro | 动态 schema、跨语言 | 性能略低 | Hadoop 生态 |
| FST | 高性能、兼容 JDK | 不支持跨语言 | Dubbo |
#### **性能对比**
```
序列化性能排名(从快到慢):
Kryo > FST > Protobuf > Hessian > Avro > JSON
序列化后大小排名(从小到大):
Protobuf ≈ Kryo < Hessian < Avro < JSON
```
#### **代码示例Protobuf**
```protobuf
// user.proto
syntax = "proto3";
message User {
int64 id = 1;
string name = 2;
string email = 3;
repeated string tags = 4;
}
```
```bash
# 编译 Protobuf
protoc --python_out=. user.proto
```
```python
# Python 序列化
import user_pb2
user = user_pb2.User()
user.id = 1
user.name = "Alice"
user.email = "alice@example.com"
user.tags.extend(["vip", "active"])
# 序列化
serialized = user.SerializeToString() # 二进制数据
# 反序列化
user2 = user_pb2.User()
user2.ParseFromString(serialized)
```
---
### 7. RPC 框架选型
#### **选型决策树**
```
是否需要跨语言调用?
├─ 是 → gRPCProtobuf 跨语言支持最好)
└─ 否 → 继续判断
是否需要高性能?
├─ 是 → DubboTCP 长连接、Hessian 序列化)
└─ 否 → 继续判断
是否需要简单易用?
├─ 是 → Spring Cloud OpenFeign基于 HTTP REST
└─ 否 → Dubbo
已有技术栈?
├─ Spring Cloud → OpenFeign/Dubbo
├─ Kubernetes → gRPC服务网格友好
└─ Dubbo → 继续使用 Dubbo
```
#### **实际项目经验**
**场景 1电商内部服务**
```
选择Dubbo
原因:
- 内部服务,都是 Java 技术栈
- 对性能要求高(高并发下单)
- 需要负载均衡、熔断降级
配置:
- 使用 Hessian 序列化
- Zookeeper 注册中心
- LeastActive 负载均衡
```
**场景 2跨语言微服务**
```
选择gRPC
原因:
- 后端 Java数据分析 PythonAI 服务 Go
- 需要统一的服务间通信协议
- Protobuf 高性能且跨语言
配置:
- Protobuf 定义接口
- HTTP/2 传输
- 多语言代码生成
```
---
### 8. 超时、重试和熔断
#### **超时配置**
```xml
<!-- Dubbo 超时 -->
<dubbo:reference id="userService"
interface="com.example.UserService"
timeout="3000"/> <!-- 3 秒超时 -->
<!-- 方法级超时 -->
<dubbo:reference id="userService"
interface="com.example.UserService">
<dubbo:method name="getUserById" timeout="1000"/>
<dubbo:method name="listUsers" timeout="5000"/>
</dubbo:reference>
```
#### **重试机制**
```xml
<dubbo:reference id="userService"
interface="com.example.UserService"
retries="2"/> <!-- 失败后重试 2 次 -->
<!-- 工作流程 -->
第一次调用 → 失败
第二次调用 → 失败
第三次调用 → 成功/失败
```
**注意**:幂等性操作才能重试(如查询),非幂等操作(如下单)不能重试
```xml
<!-- 非幂等操作禁用重试 -->
<dubbo:method name="createOrder" retries="0"/>
```
#### **熔断降级Dubbo**
```java
// 使用 Sentinel 实现熔断
@SentinelResource(value = "getUserById",
blockHandler = "handleBlock",
fallback = "handleFallback")
public User getUserById(Long id) {
return userService.getUserById(id);
}
// 熔断处理
public User handleBlock(Long id, BlockException ex) {
// 熔断时返回默认值
return new User(-1L, "Default", "default@example.com");
}
// 降级处理
public User handleFallback(Long id, Throwable ex) {
// 异常时返回降级数据
return new User(-1L, "Fallback", "fallback@example.com");
}
```
**熔断规则配置**
```java
// Sentinel 熔断规则
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("getUserById");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // 平均响应时间
rule.setCount(100); // 100ms
rule.setTimeWindow(10); // 10 秒熔断时间
rules.add(rule);
DegradeRuleManager.loadRules(rules);
```
---
### 9. 实际项目经验
#### **场景 1订单系统性能优化**
```
问题订单创建接口延迟高2 秒)
排查:
1. 调用链追踪发现库存服务耗时最长
2. 库存服务使用 HTTP RESTJSON 序列化慢
3. 每次调用都建立新连接
解决:
1. 将库存服务从 HTTP REST 迁移到 Dubbo
2. 使用 Hessian 序列化
3. 启用长连接复用
4. 配置 LeastActive 负载均衡
结果:延迟降低到 300ms提升 85%
```
#### **场景 2服务注册中心故障**
```
问题Zookeeper 集群故障,服务调用失败
排查:
Consumer 每次调用都查询注册中心,导致无法发现服务
解决:
1. Dubbo 默认会缓存 provider 列表到本地
2. 配置缓存策略
<dubbo:registry address="zookeeper://127.0.0.1:2181"
file="${user.home}/output/dubbo.cache"/>
3. 注册中心故障时,使用本地缓存
结果:注册中心故障不影响已有服务调用
```
#### **场景 3序列化兼容性问题**
```
问题:升级服务版本后,旧客户端调用失败
原因:
- 新增字段使用了不可序列化的类型
- 客户端版本不兼容
解决:
1. Protobuf 默认兼容(新增字段不影响)
2. Hessian 需要保证序列化 ID 一致
3. 使用版本号区分服务
<dubbo:service interface="..." version="1.0.0"/>
<dubbo:service interface="..." version="2.0.0"/>
4. 灰度升级,逐步切换流量
结果:平滑升级,零停机
```
---
### 10. 阿里 P7 加分项
**架构设计能力**
- 设计过大规模 RPC 框架的集群架构(百万级 QPS
- 有自定义 RPC 框架开发经验
- 实现过服务网格与传统 RPC 框架的融合
**深度理解**
- 熟悉 Dubbo 源码SPI 机制、代理设计、集群容错)
- 理解 gRPC 的 HTTP/2 和 Protobuf 底层原理
- 有序列化协议的选型和优化经验
**性能调优**
- 优化过 TCP 参数连接池、KeepAlive、缓冲区大小
- 调整过 JVM 参数减少 GC减少对象创建、使用堆外内存
- 优化过网络参数MTU、TCP_NODELAY
**生产实践**
- 解决过 TCP 粘包/拆包问题
- 处理过序列化安全漏洞(如 Hessian 反序列化 RCE
- 实现过服务优雅上下线(注册预热、优雅停机)
**可观测性**
- 集成过分布式追踪SkyWalking、Jaeger
- 实现过 RPC 调用链路监控
- 设计过服务性能指标大盘QPS、延迟、成功率
**跨语言调用**
- 有 gRPC 多语言实现经验Java、Go、Python
- 解决过 Protobuf 跨语言兼容性问题
- 实现过动态代理生成(如 Python 调用 Java 服务)

View File

@@ -0,0 +1,424 @@
# 即时通讯系统设计
## 需求分析和数据量评估
### 需求分析
- **核心功能**:单聊、群聊、消息推送、在线状态
- **业务场景**:社交应用、企业通讯、客服系统
- **QPS评估**日消息100亿+峰值QPS 10万+
- **数据规模**用户1亿+好友关系10亿+历史消息1000亿+
### 数据量评估
- **用户表**1亿条日均查询1000万次
- **好友关系表**10亿条日均更新100万次
- **消息表**1000亿+条日增1亿+
- **群组表**1亿+条日均查询100万次
- **离线消息**100亿+条日均推送1亿+
## 核心技术难点
### 1. 高并发消息处理
- 亿级用户同时在线
- 消息的实时性要求
- 消息的可靠性保证
### 2. 消息存储优化
- 海量消息数据存储
- 消息的快速检索
- 历史消息清理
### 3. 在线状态管理
- 实时在线状态同步
- 心跳检测机制
- 离线状态管理
### 4. 消息推送优化
- 推送延迟控制
- 消息去重
- 推送失败重试
## 系统架构设计
### 总体架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 移动端APP │ │ PC客户端 │ │ Web网页 │
│ (iOS/Android)│ │ (Windows) │ │ (Web) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 负载均衡 │ │ API网关 │ │ CDN加速 │
│ (Nginx) │ │ (Gateway) │ │ (Edge) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 网关服务 │ │ 业务服务 │ │ 推送服务 │
│ (Gateway) │ │ (微服务) │ │ (Service) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└─────────────────────┼───────────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 消息队列 │ │ Redis集群 │ │ 数据库集群 │
│ (Kafka/Pulsar)│ │ (缓存+pub/sub)│ │ (MySQL分库分表)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 消息存储 │ │ 文件存储 │ │ 搜索引擎 │
│ (MongoDB) │ │ (MinIO/S3) │ │ (Elasticsearch)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 关键组件
#### 1. 流量层
- **负载均衡**Nginx L7负载均衡
- **API网关**:请求路由、限流、认证
- **CDN加速**:静态资源缓存
#### 2. 服务层
- **网关服务**:连接管理、协议转换
- **业务服务**:消息处理、关系管理
- **推送服务**:消息推送、状态同步
- **通知服务**:系统通知、消息提醒
#### 3. 存储层
- **Redis集群**:在线状态、会话管理
- **MySQL集群**:用户数据、关系数据
- **MongoDB集群**:消息存储、历史记录
- **消息队列**:异步处理、削峰填谷
#### 4. 基础设施
- **消息存储**:分布式文件系统
- **搜索引擎**:消息全文检索
- **监控系统**:实时监控告警
- **日志系统**:业务日志记录
## 数据库设计
### 用户表
```sql
CREATE TABLE `im_user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`nickname` varchar(50) NOT NULL COMMENT '昵称',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`gender` tinyint DEFAULT 0 COMMENT '性别',
`birthday` date DEFAULT NULL COMMENT '生日',
`signature` varchar(255) DEFAULT NULL COMMENT '个性签名',
`mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`last_login` timestamp DEFAULT NULL COMMENT '最后登录时间',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 好友关系表
```sql
CREATE TABLE `im_friends` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`friend_id` bigint NOT NULL COMMENT '好友ID',
`remark` varchar(50) DEFAULT NULL COMMENT '备注',
`group_name` varchar(50) DEFAULT NULL COMMENT '分组名',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_friend` (`user_id`, `friend_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_friend_id` (`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 消息表
```sql
CREATE TABLE `im_message` (
`id` bigint NOT NULL AUTO_INCREMENT,
`message_id` varchar(64) NOT NULL COMMENT '消息ID',
`from_user_id` bigint NOT NULL COMMENT '发送者ID',
`to_user_id` bigint DEFAULT NULL COMMENT '接收者ID',
`group_id` bigint DEFAULT NULL COMMENT '群组ID',
`message_type` tinyint NOT NULL COMMENT '消息类型',
`content` text COMMENT '消息内容',
`is_read` tinyint NOT NULL DEFAULT 0 COMMENT '是否已读',
`is_deleted` tinyint NOT NULL DEFAULT 0 COMMENT '是否已删除',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_message_id` (`message_id`),
KEY `idx_from_user` (`from_user_id`),
KEY `idx_to_user` (`to_user_id`),
KEY `idx_group_id` (`group_id`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 群组表
```sql
CREATE TABLE `im_group` (
`id` bigint NOT NULL AUTO_INCREMENT,
`group_id` bigint NOT NULL COMMENT '群组ID',
`group_name` varchar(100) NOT NULL COMMENT '群名称',
`avatar` varchar(255) DEFAULT NULL COMMENT '群头像',
`creator_id` bigint NOT NULL COMMENT '创建者ID',
`member_count` int NOT NULL DEFAULT 0 COMMENT '成员数',
`max_members` int DEFAULT 500 COMMENT '最大成员数',
`description` text COMMENT '群描述',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 群组成员表
```sql
CREATE TABLE `im_group_member` (
`id` bigint NOT NULL AUTO_INCREMENT,
`group_id` bigint NOT NULL COMMENT '群组ID',
`user_id` bigint NOT NULL COMMENT '用户ID',
`role` tinyint NOT NULL DEFAULT 0 COMMENT '角色',
`nickname` varchar(50) DEFAULT NULL COMMENT '群昵称',
`join_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_group_user` (`group_id`, `user_id`),
KEY `idx_group_id` (`group_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
## 缓存策略
### Redis缓存设计
```typescript
// 用户在线状态
const ONLINE_STATUS_PREFIX = 'online:';
const ONLINE_STATUS_TTL = 300; // 5分钟
// 会话信息
const SESSION_PREFIX = 'session:';
const SESSION_TTL = 3600; // 1小时
// 未读消息计数
const UNREAD_PREFIX = 'unread:';
const UNREAD_TTL = 86400; // 24小时
// 消息已读状态
const READ_PREFIX = 'read:';
const READ_TTL = 604800; // 7天
// 最近会话
const RECENT_SESSION_PREFIX = 'recent:';
const RECENT_SESSION_TTL = 86400; // 24小时
```
### 缓存策略
1. **多级缓存**
- 本地缓存Caffeine
- 分布式缓存Redis Cluster
- 内存缓存:热点数据缓存
2. **缓存更新策略**
- Write Through写入同时更新缓存
- Write Behind异步更新缓存
- Cache Invalidation定时失效
3. **消息缓存**
- 最近消息缓存
- 群组信息缓存
- 用户状态缓存
### WebSocket实现
```java
public class WebSocketHandler extends TextWebSocketHandler {
private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 用户上线
String userId = getUserIdFromSession(session);
sessions.put(userId, session);
// 更新在线状态
redisTemplate.opsForValue().set(ONLINE_STATUS_PREFIX + userId, "1", ONLINE_STATUS_TTL);
// 通知好友用户上线
notifyFriendsOnline(userId);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String userId = getUserIdFromSession(session);
Message msg = parseMessage(message.getPayload());
// 处理消息
handleMessage(userId, msg);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// 用户下线
String userId = getUserIdFromSession(session);
sessions.remove(userId);
// 更新在线状态
redisTemplate.delete(ONLINE_STATUS_PREFIX + userId);
// 通知好友用户下线
notifyFriendsOffline(userId);
}
private void handleMessage(String fromUserId, Message msg) {
switch (msg.getType()) {
case SINGLE_CHAT:
sendSingleMessage(fromUserId, msg);
break;
case GROUP_CHAT:
sendGroupMessage(fromUserId, msg);
break;
case TYPING:
sendTypingMessage(fromUserId, msg);
break;
}
}
private void sendSingleMessage(String fromUserId, Message msg) {
String toUserId = msg.getToUserId();
WebSocketSession session = sessions.get(toUserId);
if (session != null && session.isOpen()) {
// 用户在线,直接推送
session.sendMessage(new TextMessage(msg.toJson()));
} else {
// 用户离线,存储离线消息
saveOfflineMessage(fromUserId, toUserId, msg);
}
// 更新未读消息计数
updateUnreadCount(fromUserId, toUserId);
}
}
```
## 扩展性考虑
### 1. 水平扩展
- **无状态服务**:业务服务无状态化
- **数据分片**按用户ID分片
- **读写分离**:主库写入,从库读取
### 2. 垂直扩展
- **服务拆分**:网关服务、业务服务、推送服务
- **数据分层**:热数据、温数据、冷数据
- **多级缓存**本地、Redis、CDN
### 3. 消息可靠性
- **消息持久化**:消息队列持久化
- **重试机制**:消息发送失败重试
- **消息去重**ID去重机制
### 4. 容灾备份
- **多活架构**:多机房部署
- **故障转移**:自动故障检测和转移
- **数据备份**:定时备份和实时同步
## 实际项目经验
### 1. 技术栈选择
- **前端**React Native + Flutter
- **后端**Spring Boot + Node.js
- **数据库**MySQL + MongoDB + Redis
- **消息队列**Kafka + Pulsar
- **通信协议**WebSocket + MQTT
### 2. 性能优化
- **消息压缩**Gzip压缩消息内容
- **批量处理**:批量消息处理
- **连接池**:数据库连接池优化
- **缓存优化**:多级缓存策略
### 3. 运维部署
- **容器化**Docker + Kubernetes
- **CI/CD**Jenkins + GitLab
- **监控告警**ELK Stack + AlertManager
- **压测**JMeter + Locust
### 4. 安全设计
- **消息加密**:端到端加密
- **身份认证**JWT Token认证
- **消息防刷**:频率限制
- **数据脱敏**:敏感信息过滤
## 阿里P7加分项
### 1. 架构设计能力
- **高可用架构**99.99%可用性
- **高性能架构**:支持亿级消息
- **扩展性架构**:弹性扩缩容
### 2. 技术深度
- **分布式系统**:分布式缓存、分布式消息
- **通信协议**WebSocket、MQTT协议
- **实时系统**:实时消息处理
### 3. 业务理解
- **社交业务**:理解社交应用场景
- **企业通讯**:掌握企业通讯需求
- **用户行为**:分析消息使用模式
### 4. 团队管理
- **技术团队**带领30人+团队
- **项目管控**:管理亿级用户项目
- **技术方案**:主导架构设计
### 5. 前沿技术
- **AI应用**:智能回复、消息分类
- **边缘计算**:边缘节点处理
- **Serverless**:函数化服务
## 面试常见问题
### 1. 如何保证消息不丢失?
- **持久化存储**:消息队列持久化
- **重试机制**:失败消息重试
- **确认机制**消息确认ACK
- **补偿机制**:定时补偿任务
### 2. 如何处理海量消息存储?
- **分库分表**:按时间分片
- **数据归档**:冷热数据分离
- **压缩存储**:消息内容压缩
- **生命周期管理**:自动清理过期数据
### 3. 如何实现消息实时性?
- **长连接**WebSocket长连接
- **推送机制**:实时推送
- **心跳检测**:连接保持
- **故障转移**:自动重连
### 4. 如何处理消息去重?
- **消息ID**全局唯一ID
- **幂等设计**:处理重复消息
- **去重表**:已处理消息记录
- **时间窗口**:时间窗口去重
### 5. 如何优化消息推送性能?
- **批量推送**:批量消息推送
- **连接池**:连接复用
- **异步处理**非阻塞IO
- **缓存优化**:推送结果缓存

View File

@@ -0,0 +1,605 @@
# 服务网格 (Service Mesh)
## 问题
**背景**:在微服务架构中,随着服务数量增加,服务间的通信管理变得复杂。服务网格作为基础设施层,负责处理服务间通信的流量管理、安全性和可观测性。
**问题**
1. 什么是服务网格?它解决了哪些问题?
2. Istio 的核心组件有哪些?它们是如何协作的?
3. Sidecar 模式的优缺点是什么?
4. 请描述 Istio 的流量管理功能(灰度发布、蓝绿部署、熔断降级)
5. Istio 如何实现 mTLS双向 TLS
6. 在生产环境中使用服务网格遇到过哪些坑?
7. Linkerd 和 Istio 的区别是什么?如何选择?
---
## 标准答案
### 1. 服务网格概述
**定义**
服务网格是微服务架构中用于处理服务间通信的基础设施层,通常以轻量级网络代理的形式实现。
**核心功能**
- **流量管理**:路由规则、负载均衡、灰度发布
- **安全性**mTLS、JWT 验证、访问控制
- **可观测性**Metrics、Tracing、Logging
**解决的问题**
```
传统微服务架构的痛点:
├─ 服务间通信逻辑散落在每个服务中
├─ 熔断、重试、超时等逻辑重复实现
├─ 安全策略难以统一管理
├─ 可观测性数据收集困难
└─ 灰度发布、流量染色需要大量代码
服务网格的解决方案:
├─ 将通信逻辑下沉到 Sidecar 代理
├─ 控制平面统一配置管理
├─ 数据平面透明代理流量
├─ 自动收集可观测性数据
└─ 声明式 API 管理流量
```
---
### 2. Istio 核心组件
#### **架构图**
```
┌─────────────────┐
│ Control Plane │
└─────────────────┘
┌─────────────────┼─────────────────┐
│ │ │
┌─────────┐ ┌──────────┐ ┌──────────┐
│ Istiod │ │Pilot │ │Citadel │
│ (统一) │ │(流量管理) │ │(证书管理)│
└─────────┘ └──────────┘ └──────────┘
│ 配置下发
┌─────────────────────────────────────┐
│ Data Plane │
├─────────────────────────────────────┤
│ │
│ Service A Service B │
│ ┌─────────┐ ┌─────────┐ │
│ │ Envoy │◄────►│ Envoy │ │
│ │ Sidecar │ │ Sidecar │ │
│ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────┘
```
#### **核心组件详解**
**1. Istiod统一控制平面**
- **Pilot**:流量管理和配置下发
- **Citadel**:证书管理和身份认证
- **Galley**配置验证和注入Istio 1.13+ 已合并到 Istiod
**代码示例 - Istiod 配置**
```yaml
# istiod deployment
apiVersion: v1
kind: Deployment
metadata:
name: istiod
namespace: istio-system
spec:
template:
spec:
containers:
- name: discovery
image: gcr.io/istio-testing/pilot:1.19.0
args:
- "discovery"
- "--monitoringAddr=:15014"
- "--log_output_level=default:info"
ports:
- containerPort: 15012 # Pilot 服务的 xDS 端口
name: grpc-xds
```
**2. Envoy Sidecar数据平面**
- 拦截所有进出流量
- 执行流量规则(路由、负载均衡)
- 收集 Metrics 和 Traces
- 处理 mTLS 加解密
**Sidecar 注入示例**
```yaml
# 自动注入 Sidecar
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
sidecar.istio.io/inject: "true" # 启用自动注入
spec:
template:
metadata:
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true" # 重写 HTTP probes
spec:
containers:
- name: app
image: my-app:1.0.0
ports:
- containerPort: 8080
```
---
### 3. Sidecar 模式
#### **优点**
1. **透明性**:业务代码无感知,无需修改
2. **语言无关**:任何语言都能使用
3. **统一管理**:集中配置,易于维护
4. **渐进式采用**:可以逐步迁移
#### **缺点**
1. **资源开销**:每个服务都有 Sidecar增加内存和 CPU
```
典型资源占用:
- 内存50-100MB per Sidecar
- CPU5-10% per core
- 延迟增加1-5ms
```
2. **网络链路增加**
```
请求路径(有 Sidecar
Client → Sidecar A → Service A → Sidecar B → Service B
请求路径(无 Sidecar
Client → Service A → Service B
```
3. **调试复杂度**:多了一层网络代理
#### **优化方案**
```yaml
# Sidecar 资源限制
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: istio-proxy
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
```
**Sidecar 资源配置模式**
```yaml
# sidecar resources customization
apiVersion: v1
kind: ConfigMap
metadata:
name: istio-sidecar-injector
data:
values: |
sidecarResources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
```
---
### 4. 流量管理
#### **4.1 灰度发布 (Canary Deployment)**
**场景**:新版本 v2 发布给 10% 的流量
```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
x-canary:
exact: "true" # 带特定 header 的流量走 v2
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
weight: 90 # 90% 流量走 v1
- destination:
host: reviews
subset: v2
weight: 10 # 10% 流量走 v2
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
```
#### **4.2 蓝绿部署 (Blue-Green Deployment)**
**场景**:一键切换全部流量到新版本
```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-app
spec:
hosts:
- my-app
http:
- route:
- destination:
host: my-app
subset: blue # 所有流量指向 blue
weight: 100
# 切换到 green修改 subset 为 green
---
# Kubernetes Deployment同时存在 blue 和 green
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-blue
spec:
template:
metadata:
labels:
version: blue
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-green
spec:
template:
metadata:
labels:
version: green
```
#### **4.3 熔断降级 (Circuit Breaker)**
**场景**:防止故障扩散
```yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 10 # 最大连接数
http:
http1MaxPendingRequests: 50 # 最大等待请求数
http2MaxRequests: 100 # 最大并发请求数
maxRequestsPerConnection: 2 # 每连接最大请求数
maxRetries: 3 # 最大重试次数
outlierDetection:
consecutiveErrors: 5 # 连续 5 次错误
interval: 30s # 每 30s 检查一次
baseEjectionTime: 30s # 最小熔断时间
maxEjectionPercent: 50 # 最多熔断 50% 的实例
minHealthPercent: 40 # 最小健康实例比例
```
**熔断状态图**
```
Closed → Open → Half-Open → Closed
↑ │ │
└────────┴──────────┘
```
#### **4.4 超时和重试**
```yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- retry:
attempts: 3 # 最多重试 3 次
perTryTimeout: 2s # 每次重试超时 2s
retryOn: 5xx,connect-failure,refused-stream # 重试条件
timeout: 10s # 总超时时间
route:
- destination:
host: reviews
```
---
### 5. mTLS (双向 TLS) 实现
#### **原理**
```
Service A Service B
│ │
│ 1. 发送连接请求(无证书) │
│ ─────────────────────────────────────►│
│ │
│ 2. 返回服务器证书 │
│ ◄─────────────────────────────────────│
│ │
│ 3. 发送客户端证书 │
│ ─────────────────────────────────────►│
│ │
│ 4. 验证通过,建立加密连接 │
│ ◄────────────────────────────────────►│
│ │
│ 5. 加密通信 │
│ ◄──────────────► │
```
#### **配置示例**
**全局启用 mTLS**
```yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: istio-system
spec:
mtls:
mode: STRICT # 严格模式:必须使用 mTLS
```
**按服务配置**
```yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: my-app-mtls
namespace: default
spec:
selector:
matchLabels:
app: my-app
mtls:
mode: PERMISSIVE # 宽松模式:兼容 mTLS 和明文
```
**服务授权**
```yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: my-app-authz
spec:
selector:
matchLabels:
app: my-app
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/frontend"] # 只允许 frontend SA 访问
to:
- operation:
methods: ["GET", "POST"]
```
#### **证书管理流程**
```
1. Citadel 工作负载证书
2. 证书存储在 Secret 中
3. Envoy Sidecar 启动时加载证书
4. 定期轮换证书(默认 24 小时)
5. 旧证书过期,使用新证书
```
---
### 6. 生产环境踩坑经验
#### **坑 1Sidecar 资源占用过高**
```yaml
# 问题100 个服务 × 100MB = 10GB 内存
# 解决:按需启用 Sidecar
apiVersion: v1
kind: Pod
metadata:
name: my-app
annotations:
sidecar.istio.io/inject: "false" # 禁用 Sidecar
```
#### **坑 2网络延迟增加**
```
问题:请求延迟从 5ms 增加到 10ms
原因:
- Sidecar 增加了一跳
- mTLS 加解密开销
解决:
1. 调整 Envoy 配置,减少日志级别
2. 使用 PERMISSIVE 模式降级
3. 增加超时时间配置
```
#### **坑 3配置下发延迟**
```yaml
# 问题:修改 VirtualService 后,流量未立即切换
# 原因Pilot 下发配置有延迟(默认 1s
# 解决:减少配置刷新间隔
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
data:
mesh: |-
defaultConfig:
proxyStatsMatcher:
inclusionRegexps:
- ".*" # 收集所有指标
discoveryRefreshDelay: 1s # 配置刷新延迟
```
```
#### **坑 4大规模性能问题**
```
问题:集群 1000+ 服务时Istiod 性能瓶颈
解决:
1. 部署多个 Istiod 实例
2. 使用 Namespace 隔离配置
3. 启用配置压缩
```
**多实例部署**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: istiod
spec:
replicas: 3 # 多副本
```
---
### 7. Linkerd vs Istio
#### **对比表**
| 特性 | Linkerd 2.x | Istio |
|------|-------------|-------|
| 代理 | Rust 实现Linkerd2-proxy | EnvoyC++ |
| 性能 | 更低资源占用 | 资源占用较高 |
| 功能 | 聚焦核心功能 | 功能更丰富 |
| 集成 | Kubernetes 原生 | 支持多平台 |
| 学习曲线 | 简单 | 复杂 |
| 社区 | CNCF 毕业项目 | CNCF 孵化中 |
| 多集群支持 | 弱 | 强 |
| 流量管理 | 基础 | 高级(灰度、蓝绿等) |
#### **选择建议**
**选择 Linkerd**
- Kubernetes 原生环境
- 重视性能和资源占用
- 需要简单易用的解决方案
- 功能要求不高
**选择 Istio**
- 需要高级流量管理
- 多集群/多云环境
- 需要细粒度的安全控制
- 团队有运维能力
---
### 8. 实际项目经验
#### **场景 1电商系统灰度发布**
```
需求:新支付系统先给 5% 用户试用
方案:
1. 部署 payment-v2
2. 配置 VirtualService5% 流量走 v2
3. 监控错误率和延迟
4. 逐步增加流量比例5% → 20% → 50% → 100%
5. 出现问题立即回滚
```
#### **场景 2金融系统 mTLS 合规**
```
需求:所有服务间通信必须加密
方案:
1. 启用 STRICT mTLS 模式
2. 配置 AuthorizationPolicy只允许合法的 SA 访问
3. 定期轮换证书24 小时)
4. 审计日志记录所有通信
```
#### **场景 3多集群容灾**
```
需求:主集群故障时自动切换到备用集群
方案:
1. 使用 Multi-Cluster Mesh
2. 配置 ServiceEntry指向备用集群
3. 配置 DestinationRule故障时自动切换
4. 跨集群流量加密
```
---
### 9. 阿里 P7 加分项
**架构设计能力**
- 设计过大规模服务网格架构500+ 服务)
- 有多集群/多云服务网格实施经验
- 实现过自定义 Control Plane如基于 Istio API
**深度理解**
- 理解 Envoy 内部机制过滤器链、连接池、HTTP/2
- 熟悉 xDS 协议CDS, EDS, LDS, RDS
- 有性能调优经验(减少延迟、优化资源占用)
**实际项目**
- 主导过从传统架构迁移到服务网格
- 解决过生产环境的疑难问题(如网络分区、证书轮换故障)
- 开发过自定义 WASM 插件扩展 Envoy 功能
**开源贡献**
- 向 Istio/Envoy 社区提交过 PR
- 解决过社区 Issue
- 编写过相关技术博客或演讲
**监控和可观测性**
- 设计过服务网格监控体系
- 使用 Prometheus/Grafana 监控 Sidecar 性能
- 实现过分布式追踪集成Jaeger/Zipkin
**安全实践**
- 实现过零信任网络架构
- 有安全审计和合规经验
- 设计过细粒度的 RBAC 策略

View File

@@ -0,0 +1,359 @@
# 短链接系统设计
## 需求分析和数据量评估
### 需求分析
- **核心功能**:长链接转短链接、短链接跳转、统计分析
- **业务场景**:短信营销、社交媒体分享、广告推广
- **QPS评估**日点击量10亿次峰值QPS 3万+
- **数据规模**短链接10亿+日生成1000万+
### 数据量评估
- **短链接表**10亿条日均写入1000万次
- **原始链接表**10亿条日均读取10亿次
- **访问统计表**100亿+条日增1亿+
- **用户表**1000万+日均查询100万次
## 核心技术难点
### 1. 高并发写入
- 短链接生成需要高性能
- 避免数据库写入瓶颈
- 分布式ID生成
### 2. 高性能读取
- 毫秒级响应时间
- 缓存命中率优化
- 全球CDN加速
### 3. 长链接查重
- 重复链接检测
- 去重策略设计
- 一致性保证
### 4. 统计准确性
- 实时统计延迟
- 统计数据准确性
- 分布式计数器
## 系统架构设计
### 总体架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CDN/Edge │ │ Load Balance │ │ API Gateway │
│ Cache │◄──►│ (Anycast) │◄──►│ (Gateway) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌───────────────────────────────────┼───────────────────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 短链接服务 │ │ 统计服务 │ │ 监控服务 │
│ (微服务) │ │ (微服务) │ │ (微服务) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────────────────┼───────────────────────────────────┘
┌───────────────────────────────────┼───────────────────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Redis集群 │ │ 消息队列 │ │ 数据库集群 │
│ (缓存+计数器)│ │ (Kafka) │ │ (MySQL分库分表)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌───────────────────────────────────┼───────────────────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 时序数据库 │ │ 数据仓库 │ │ 搜索引擎 │
│ (InfluxDB) │ │ (ClickHouse) │ │ (Elasticsearch)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 关键组件
#### 1. 流量层
- **CDN/Edge**:全球加速,缓存热点短链接
- **负载均衡**Anycast IP就近接入
- **API网关**:限流、路由、认证
#### 2. 服务层
- **短链接服务**:核心业务逻辑
- **统计服务**:访问统计和报表
- **管理服务**:后台管理系统
- **监控服务**:实时监控告警
#### 3. 存储层
- **Redis集群**:缓存和计数器
- **MySQL集群**:主从复制,分库分表
- **时序数据库**:时序数据存储
- **搜索引擎**:链接检索和分析
#### 4. 分析层
- **数据仓库**:离线数据分析
- **OLAP引擎**:实时查询分析
- **报表系统**:业务报表展示
## 数据库设计
### 短链接表
```sql
CREATE TABLE `short_url` (
`id` bigint NOT NULL AUTO_INCREMENT,
`short_code` varchar(10) NOT NULL COMMENT '短链接编码',
`long_url` text NOT NULL COMMENT '原始长链接',
`domain` varchar(255) NOT NULL COMMENT '自定义域名',
`title` varchar(255) DEFAULT NULL COMMENT '页面标题',
`description` text COMMENT '页面描述',
`keywords` varchar(500) DEFAULT NULL COMMENT '关键词',
`user_id` bigint DEFAULT NULL COMMENT '用户ID',
`is_custom` tinyint NOT NULL DEFAULT 0 COMMENT '是否自定义',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`expire_at` datetime DEFAULT NULL COMMENT '过期时间',
`click_count` int NOT NULL DEFAULT 0 COMMENT '点击次数',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_short_code` (`short_code`),
KEY `idx_long_url` (`long_url`(255)),
KEY `idx_user_id` (`user_id`),
KEY `idx_expire_at` (`expire_at`),
KEY `idx_domain` (`domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 访问记录表
```sql
CREATE TABLE `url_access_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`short_code` varchar(10) NOT NULL COMMENT '短链接编码',
`ip` varchar(45) NOT NULL COMMENT '访问IP',
`user_agent` text COMMENT '用户代理',
`referer` text COMMENT '来源页面',
`country` varchar(50) DEFAULT NULL COMMENT '国家',
`region` varchar(50) DEFAULT NULL COMMENT '地区',
`city` varchar(50) DEFAULT NULL COMMENT '城市',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_short_code` (`short_code`),
KEY `idx_created_at` (`created_at`),
KEY `idx_ip` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 统计表
```sql
CREATE TABLE `url_stats` (
`id` bigint NOT NULL AUTO_INCREMENT,
`short_code` varchar(10) NOT NULL COMMENT '短链接编码',
`date` date NOT NULL COMMENT '统计日期',
`total_clicks` int NOT NULL DEFAULT 0 COMMENT '总点击次数',
`unique_clicks` int NOT NULL DEFAULT 0 COMMENT '独立点击次数',
`by_country` json DEFAULT NULL COMMENT '国家分布',
`by_region` json DEFAULT NULL COMMENT '地区分布',
`by_device` json DEFAULT NULL COMMENT '设备分布',
`by_browser` json DEFAULT NULL COMMENT '浏览器分布',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_date_code` (`date`, `short_code`),
KEY `idx_short_code` (`short_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 用户表
```sql
CREATE TABLE `short_url_user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`email` varchar(100) NOT NULL COMMENT '邮箱',
`domain` varchar(255) DEFAULT NULL COMMENT '自定义域名',
`api_key` varchar(64) DEFAULT NULL COMMENT 'API密钥',
`quota` int NOT NULL DEFAULT 1000 COMMENT '配额',
`used` int NOT NULL DEFAULT 0 COMMENT '已使用',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_id` (`user_id`),
UNIQUE KEY `uk_api_key` (`api_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
## 缓存策略
### Redis缓存设计
```typescript
// 短链接缓存
const SHORT_URL_CACHE_PREFIX = 'short_url:';
const SHORT_URL_CACHE_TTL = 86400; // 24小时
// 访问计数器
const CLICK_COUNT_PREFIX = 'click:';
const CLICK_COUNT_TTL = 60; // 1分钟
// 布隆过滤器
const BLOOM_FILTER_PREFIX = 'bloom:';
const BLOOM_FILTER_SIZE = 1000000000; // 10亿
// 限流计数器
const RATE_LIMIT_PREFIX = 'rate_limit:';
const RATE_LIMIT_TTL = 60; // 1分钟
```
### 缓存策略
1. **多级缓存**
- 本地缓存Caffeine
- 分布式缓存Redis Cluster
- CDN缓存边缘节点
2. **缓存更新策略**
- Write Through写入同时更新缓存
- Write Back异步更新缓存
- Refresh Ahead预加载热点数据
3. **缓存预热**
- 热门短链接预加载
- 统计数据预计算
- 静态资源预缓存
### 布隆过滤器实现
```java
public class BloomFilter {
private final BitSet bitSet;
private final int size;
private final int[] hashSeeds;
public BloomFilter(int size, int hashCount) {
this.size = size;
this.bitSet = new BitSet(size);
this.hashSeeds = new int[hashCount];
Random random = new Random();
for (int i = 0; i < hashCount; i++) {
hashSeeds[i] = random.nextInt();
}
}
public void add(String key) {
for (int seed : hashSeeds) {
int hash = Math.abs((key.hashCode() ^ seed) % size);
bitSet.set(hash, true);
}
}
public boolean mightContain(String key) {
for (int seed : hashSeeds) {
int hash = Math.abs((key.hashCode() ^ seed) % size);
if (!bitSet.get(hash)) {
return false;
}
}
return true;
}
}
```
## 扩展性考虑
### 1. 水平扩展
- **无状态服务**:短链接服务无状态化
- **数据分片**:按短链接编码分片
- **读写分离**:主库写入,从库读取
### 2. 垂直扩展
- **服务拆分**API服务、统计服务、管理服务
- **数据分层**:热数据、温数据、冷数据
- **多级缓存**本地、Redis、CDN
### 3. 全球化部署
- **CDN加速**:全球节点部署
- **地域化存储**:按地域分片
- **灾备切换**:多机房容灾
### 4. 监控告警
- **实时监控**QPS、响应时间、错误率
- **业务监控**:点击量、转化率
- **异常告警**:服务异常、数据异常
## 实际项目经验
### 1. 技术栈选择
- **前端**React + TypeScript
- **后端**Spring Boot + Node.js
- **数据库**MySQL + Redis
- **缓存**Redis Cluster
- **消息队列**Kafka
- **监控**Prometheus + Grafana
### 2. 性能优化
- **短链接生成**Snowflake算法
- **缓存优化**:多级缓存策略
- **数据库优化**:分库分表、索引优化
- **网络优化**HTTP/2、Keep-Alive
### 3. 运维部署
- **容器化**Docker + Kubernetes
- **CI/CD**Jenkins + GitLab
- **监控告警**ELK Stack + AlertManager
- **压测**JMeter + Locust
### 4. 安全设计
- **HTTPS**:全链路加密
- **API限流**:防刷、防攻击
- **数据脱敏**:敏感信息加密
- **访问控制**API密钥认证
## 阿里P7加分项
### 1. 架构设计能力
- **高可用架构**99.99%可用性
- **高性能架构**支持亿级QPS
- **全球化架构**全球CDN加速
### 2. 技术深度
- **分布式算法**:一致性哈希、布隆过滤器
- **缓存优化**:多级缓存策略
- **数据库优化**:分库分表、读写分离
### 3. 业务理解
- **营销业务**:理解短链接在营销中的应用
- **用户行为**:分析点击行为模式
- **数据统计**:实时统计和离线分析
### 4. 团队管理
- **技术团队**带领15人+团队
- **项目管控**:管理亿级用户项目
- **技术方案**:主导技术架构设计
### 5. 前沿技术
- **Serverless**:短链接函数化
- **边缘计算**:边缘节点处理
- **AI应用**:智能推荐、异常检测
## 面试常见问题
### 1. 短链接如何生成?
- **随机字符**:生成随机字符串
- **自增序列**数据库自增ID
- **哈希算法**MD5/SHA1取前几位
- **Base62编码**数字转62进制
### 2. 如何避免短链接冲突?
- **布隆过滤器**:快速检测重复
- **数据库唯一索引**:保证唯一性
- **重试机制**:冲突时重新生成
### 3. 如何实现高并发生成?
- **预生成**:批量生成短链接
- **分布式ID**Snowflake算法
- **内存缓存**:减少数据库访问
### 4. 如何统计点击数据?
- **实时统计**Redis计数器
- **异步处理**:消息队列存储
- **离线分析**:数据仓库计算
### 5. 如何保证短链接安全?
- **链接过滤**:过滤恶意链接
- **访问控制**:黑白名单
- **HTTPS加密**:防止劫持
- **IP限制**:防刷机制

View File

@@ -0,0 +1,444 @@
# 社交信息流系统设计
## 需求分析和数据量评估
### 需求分析
- **核心功能**:信息流展示、个性化推荐、社交互动、内容管理
- **业务场景**:微博、朋友圈、抖音等社交应用
- **QPS评估**日请求100亿+峰值QPS 20万+
- **数据规模**用户5亿+内容100亿+关系数据1000亿+
### 数据量评估
- **用户表**5亿条日均查询1亿次
- **内容表**100亿条日增1亿+
- **关系表**1000亿+条日均更新10亿次
- **互动表**500亿+条日增5亿+
- **推荐系统**日处理1000亿次推荐请求
## 核心技术难点
### 1. 海量内容处理
- 亿级内容的存储和检索
- 内容的实时分发和推送
- 内容的审核和过滤
### 2. 个性化推荐
- 用户兴趣建模
- 实时推荐算法
- 推荐效果评估
### 3. 高并发读取
- 信息流的实时性要求
- 用户关系计算
- 数据缓存优化
### 4. 社交图谱构建
- 用户关系网络
- 关系强度计算
- 图算法优化
## 系统架构设计
### 总体架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 移动端APP │ │ Web网页 │ │ API接口 │
│ (iOS/Android)│ │ (PC/移动) │ │ (第三方) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────┼───────────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 负载均衡 │ │ API网关 │ │ CDN加速 │
│ (Nginx) │ │ (Gateway) │ │ (Edge) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Feed服务 │ │ 互动服务 │ │ 推荐服务 │
│ (微服务) │ │ (微服务) │ │ (微服务) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└─────────────────────┼───────────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 缓存集群 │ │ 数据库集群 │ │ 消息队列 │
│ (Redis) │ │ (MySQL分库分表)│ │ (Kafka) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────────┼───────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 搜索引擎 │ │ 图数据库 │ │ 数据仓库 │
│ (Elasticsearch)│ │ (Neo4j) │ │ (ClickHouse) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 关键组件
#### 1. 流量层
- **负载均衡**Nginx L7负载均衡
- **API网关**:请求路由、限流、认证
- **CDN加速**:静态资源缓存
#### 2. 服务层
- **Feed服务**:信息流生成和分发
- **互动服务**:点赞、评论、分享处理
- **推荐服务**:个性化推荐算法
- **社交服务**:关系管理
#### 3. 存储层
- **Redis集群**:缓存、计数器
- **MySQL集群**:用户数据、内容数据
- **MongoDB集群**Feed流数据
- **图数据库**:社交关系数据
#### 4. 基础设施
- **搜索引擎**:内容全文检索
- **消息队列**:异步处理、削峰填谷
- **数据仓库**:离线数据分析
- **推荐引擎**:机器学习平台
## 数据库设计
### 用户表
```sql
CREATE TABLE `feed_user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`nickname` varchar(50) NOT NULL COMMENT '昵称',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`gender` tinyint DEFAULT 0 COMMENT '性别',
`birthday` date DEFAULT NULL COMMENT '生日',
`location` varchar(100) DEFAULT NULL COMMENT '位置',
`bio` varchar(255) DEFAULT NULL COMMENT '个人简介',
`interests` json DEFAULT NULL COMMENT '兴趣标签',
`follow_count` int NOT NULL DEFAULT 0 COMMENT '关注数',
`follower_count` int NOT NULL DEFAULT 0 COMMENT '粉丝数',
`post_count` int NOT NULL DEFAULT 0 COMMENT '发布数',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 内容表
```sql
CREATE TABLE `feed_content` (
`id` bigint NOT NULL AUTO_INCREMENT,
`content_id` varchar(64) NOT NULL COMMENT '内容ID',
`user_id` bigint NOT NULL COMMENT '用户ID',
`content_type` tinyint NOT NULL COMMENT '内容类型',
`title` varchar(255) DEFAULT NULL COMMENT '标题',
`content` text NOT NULL COMMENT '内容',
`media_urls` json DEFAULT NULL COMMENT '媒体URLs',
`tags` json DEFAULT NULL COMMENT '标签',
`like_count` int NOT NULL DEFAULT 0 COMMENT '点赞数',
`comment_count` int NOT NULL DEFAULT 0 COMMENT '评论数',
`share_count` int NOT NULL DEFAULT 0 COMMENT '分享数',
`view_count` int NOT NULL DEFAULT 0 COMMENT '浏览数',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_content_id` (`content_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_created_at` (`created_at`),
FULLTEXT KEY `idx_content` (`title`, `content`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 用户关系表
```sql
CREATE TABLE `feed_relationship` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`follow_user_id` bigint NOT NULL COMMENT '关注用户ID',
`relation_type` tinyint NOT NULL DEFAULT 1 COMMENT '关系类型',
`strength` decimal(5,2) DEFAULT '0.00' COMMENT '关系强度',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_follow` (`user_id`, `follow_user_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_follow_user_id` (`follow_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### Feed流表
```sql
CREATE TABLE `feed_stream` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`content_id` varchar(64) NOT NULL COMMENT '内容ID',
`feed_type` tinyint NOT NULL COMMENT 'Feed类型',
`priority` decimal(10,4) NOT NULL DEFAULT '0.0000' COMMENT '优先级',
`is_read` tinyint NOT NULL DEFAULT 0 COMMENT '是否已读',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_priority` (`priority`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 互动记录表
```sql
CREATE TABLE `feed_interaction` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`target_user_id` bigint DEFAULT NULL COMMENT '目标用户ID',
`content_id` varchar(64) DEFAULT NULL COMMENT '内容ID',
`interaction_type` tinyint NOT NULL COMMENT '互动类型',
`content` text DEFAULT NULL COMMENT '互动内容',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_target_user_id` (`target_user_id`),
KEY `idx_content_id` (`content_id`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
## 缓存策略
### Redis缓存设计
```typescript
// 用户信息缓存
const USER_INFO_PREFIX = 'user:';
const USER_INFO_TTL = 3600; // 1小时
// 内容信息缓存
const CONTENT_INFO_PREFIX = 'content:';
const CONTENT_INFO_TTL = 86400; // 24小时
// Feed流缓存
const FEED_STREAM_PREFIX = 'feed:';
const FEED_STREAM_TTL = 1800; // 30分钟
// 互动计数器
const INTERACTION_PREFIX = 'interaction:';
const INTERACTION_TTL = 300; // 5分钟
// 推荐结果缓存
const RECOMMEND_PREFIX = 'recommend:';
const RECOMMEND_TTL = 300; // 5分钟
// 社交关系缓存
const RELATION_PREFIX = 'relation:';
const RELATION_TTL = 3600; // 1小时
```
### 缓存策略
1. **多级缓存**
- 本地缓存Caffeine
- 分布式缓存Redis Cluster
- CDN缓存静态资源
2. **缓存更新策略**
- Write Behind异步更新
- Refresh Ahead预加载热点数据
- Cache Invalidation定时失效
3. **Feed流缓存**
- 分页缓存
- 用户个性化缓存
- 实时更新策略
### Feed流生成算法
```java
public class FeedGenerator {
// 基于时间线的基础Feed
public List<FeedItem> generateTimelineFeed(String userId, int offset, int limit) {
// 从Redis获取用户关注列表
List<String> followUsers = getFollowUsers(userId);
// 获取关注用户的最新内容
List<FeedItem> feeds = new ArrayList<>();
for (String followUser : followUsers) {
List<FeedItem> userFeeds = getUserRecentFeeds(followUser, offset, limit / followUsers.size());
feeds.addAll(userFeeds);
}
// 按时间排序
return feeds.stream()
.sorted(Comparator.comparing(FeedItem::getCreatedAt).reversed())
.skip(offset)
.limit(limit)
.collect(Collectors.toList());
}
// 个性化推荐Feed
public List<FeedItem> generateRecommendFeed(String userId, int offset, int limit) {
// 获取用户兴趣标签
List<String> interests = getUserInterests(userId);
// 基于协同过滤推荐内容
List<String> recommendContentIds = collaborativeFiltering(userId, interests);
// 基于内容的推荐
List<String> contentBasedRecommend = contentBasedRecommend(userId);
// 合并推荐结果
Set<String> allRecommend = new HashSet<>();
allRecommend.addAll(recommendContentIds);
allRecommend.addAll(contentBasedRecommend);
// 获取推荐内容详情
List<FeedItem> feeds = getContentDetails(new ArrayList<>(allRecommend));
// 排序并返回
return feeds.stream()
.sorted(Comparator.comparing(FeedItem::getScore).reversed())
.skip(offset)
.limit(limit)
.collect(Collectors.toList());
}
// 混合Feed流
public List<FeedItem> generateHybridFeed(String userId, int offset, int limit) {
List<FeedItem> timelineFeeds = generateTimelineFeed(userId, 0, limit / 2);
List<FeedItem> recommendFeeds = generateRecommendFeed(userId, 0, limit / 2);
// 合并并去重
Set<String> seenContentIds = new HashSet<>();
List<FeedItem> result = new ArrayList<>();
for (FeedItem feed : timelineFeeds) {
if (!seenContentIds.contains(feed.getContentId())) {
result.add(feed);
seenContentIds.add(feed.getContentId());
}
}
for (FeedItem feed : recommendFeeds) {
if (!seenContentIds.contains(feed.getContentId())) {
result.add(feed);
seenContentIds.add(feed.getContentId());
}
}
// 按权重排序
return result.stream()
.sorted(Comparator.comparing(FeedItem::getScore).reversed())
.skip(offset)
.limit(limit)
.collect(Collectors.toList());
}
}
```
## 扩展性考虑
### 1. 水平扩展
- **无状态服务**Feed服务、推荐服务无状态化
- **数据分片**按用户ID分片
- **读写分离**:主库写入,从库读取
### 2. 垂直扩展
- **服务拆分**Feed服务、推荐服务、互动服务
- **数据分层**:热数据、温数据、冷数据
- **多级缓存**本地、Redis、CDN
### 3. 推荐算法扩展
- **实时推荐**:基于实时行为更新
- **离线推荐**:批量处理推荐结果
- **冷启动**:新用户推荐策略
### 4. 容灾备份
- **多活架构**:多机房部署
- **故障转移**:自动故障检测和转移
- **数据备份**:定时备份和实时同步
## 实际项目经验
### 1. 技术栈选择
- **前端**React + TypeScript + Mobile
- **后端**Spring Boot + Node.js + Python
- **数据库**MySQL + MongoDB + Redis
- **消息队列**Kafka + Pulsar
- **搜索引擎**Elasticsearch + ClickHouse
### 2. 性能优化
- **Feed缓存**:多级缓存策略
- **数据库优化**:分库分表、索引优化
- **算法优化**:推荐算法优化
- **网络优化**HTTP/2、Keep-Alive
### 3. 运维部署
- **容器化**Docker + Kubernetes
- **CI/CD**Jenkins + GitLab
- **监控告警**ELK Stack + AlertManager
- **压测**JMeter + Locust
### 4. 安全设计
- **内容安全**:内容审核、过滤
- **用户隐私**:数据脱敏、权限控制
- **防刷机制**:频率限制、行为分析
## 阿里P7加分项
### 1. 架构设计能力
- **高可用架构**99.99%可用性
- **高性能架构**支持亿级QPS
- **扩展性架构**:弹性扩缩容
### 2. 技术深度
- **推荐系统**:协同过滤、深度学习
- **实时计算**Flink、Kafka Streams
- **图算法**:社交图谱、关系计算
### 3. 业务理解
- **社交业务**:理解社交网络特性
- **用户行为**:分析用户互动模式
- **内容生态**:掌握内容分发逻辑
### 4. 团队管理
- **技术团队**带领50人+团队
- **项目管控**:管理亿级用户项目
- **技术方案**:主导架构设计
### 5. 前沿技术
- **AI应用**:智能推荐、内容生成
- **边缘计算**:边缘节点处理
- **Serverless**:函数化服务
## 面试常见问题
### 1. 如何生成个性化信息流?
- **用户画像**:用户兴趣建模
- **推荐算法**:协同过滤、基于内容
- **实时更新**:实时行为追踪
- **多目标优化**:点击率、停留时间
### 2. 如何处理高并发Feed请求
- **缓存策略**:多级缓存
- **数据预加载**Feed预生成
- **异步处理**:异步更新
- **分页优化**:游标分页
### 3. 如何保证Feed流实时性
- **实时推送**WebSocket推送
- **增量更新**:实时增量计算
- **事件驱动**:事件总线
- **缓存预热**:热点数据预热
### 4. 如何实现推荐算法?
- **协同过滤**:用户行为相似度
- **内容分析**:内容特征提取
- **深度学习**:神经网络模型
- **多臂老虎机**:探索与利用
### 5. 如何处理海量数据?
- **分库分表**按用户ID分片
- **数据归档**:冷热数据分离
- **缓存优化**:热点数据缓存
- **计算优化**:批量处理、并行计算

View File

@@ -0,0 +1,318 @@
# 秒杀系统设计
## 需求分析和数据量评估
### 需求分析
- **核心功能**:商品秒杀、库存管理、下单支付、用户限流
- **业务场景**双十一、618等大促活动商品短时间内高并发抢购
- **QPS评估**假设10万用户同时抢购QPS可达10万+
- **峰值预期**高峰期QPS可达50万+
- **数据规模**商品10万+用户1000万+订单日峰值1亿+
### 数据量评估
- **商品表**10万条日均查询100万次
- **库存表**10万条秒杀期间读写10万+/秒
- **订单表**日峰值1亿条历史数据10亿+
- **用户表**1000万条日均查询500万次
- **Redis缓存**商品信息100万条库存信息10万条
## 核心技术难点
### 1. 高并发库存管理
- 传统数据库锁无法支撑高并发
- 需要分布式锁配合缓存实现
- 库存扣减的原子性问题
### 2. 超卖问题
- 库存与订单不一致
- 需要最终一致性保证
- 重复下单处理
### 3. 限流策略
- 全局限流、用户限流、商品限流
- 限流算法选择(令牌桶、漏桶)
- 限流后的用户体验
### 4. 数据一致性
- 缓存与数据库的一致性
- 分布式事务处理
- 幂等性保证
## 系统架构设计
### 总体架构
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CDN/Static │ │ Load Balance │ │ API Gateway │
│ Cache │◄──►│ (Nginx) │◄──►│ (Gateway) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌───────────────────────────────────┼───────────────────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 业务服务 │ │ 业务服务 │ │ 业务服务 │
│ (微服务) │ │ (微服务) │ │ (微服务) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────────────────────────┼───────────────────────────────────┘
┌───────────────────────────────────┼───────────────────────────────────┐
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Redis集群 │ │ 消息队列 │ │ 数据库集群 │
│ (缓存+分布式锁)│ │ (Kafka/RocketMQ)│ │ (MySQL分库分表)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### 关键组件
#### 1. 流量层
- **CDN**:静态资源加速
- **Web服务器**Nginx负载均衡
- **API网关**:限流、路由、认证
#### 2. 服务层
- **秒杀服务**:核心业务逻辑
- **订单服务**:订单处理
- **库存服务**:库存管理
- **支付服务**:支付处理
#### 3. 存储层
- **Redis集群**:缓存和分布式锁
- **数据库集群**MySQL分库分表
- **消息队列**:异步处理
#### 4. 监控层
- **监控系统**:实时监控
- **告警系统**:异常告警
- **日志系统**:业务日志
## 数据库设计
### 商品表
```sql
CREATE TABLE `seckill_product` (
`id` bigint NOT NULL AUTO_INCREMENT,
`product_id` bigint NOT NULL COMMENT '商品ID',
`product_name` varchar(255) NOT NULL COMMENT '商品名称',
`product_desc` text COMMENT '商品描述',
`original_price` decimal(10,2) NOT NULL COMMENT '原价',
`seckill_price` decimal(10,2) NOT NULL COMMENT '秒杀价',
`stock_count` int NOT NULL COMMENT '库存数量',
`seckill_count` int NOT NULL DEFAULT 0 COMMENT '已秒杀数量',
`start_time` datetime NOT NULL COMMENT '开始时间',
`end_time` datetime NOT NULL COMMENT '结束时间',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_id` (`product_id`),
KEY `idx_start_time` (`start_time`),
KEY `idx_end_time` (`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 订单表
```sql
CREATE TABLE `seckill_order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_no` varchar(64) NOT NULL COMMENT '订单号',
`user_id` bigint NOT NULL COMMENT '用户ID',
`product_id` bigint NOT NULL COMMENT '商品ID',
`product_name` varchar(255) NOT NULL COMMENT '商品名称',
`seckill_price` decimal(10,2) NOT NULL COMMENT '秒杀价',
`status` tinyint NOT NULL DEFAULT 0 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`),
KEY `idx_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 用户表
```sql
CREATE TABLE `seckill_user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`email` varchar(100) NOT NULL COMMENT '邮箱',
`phone` varchar(20) NOT NULL COMMENT '手机号',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
## 缓存策略
### Redis缓存设计
```typescript
// 商品信息缓存
const PRODUCT_CACHE_PREFIX = 'product:';
const PRODUCT_CACHE_TTL = 3600; // 1小时
// 库存缓存
const STOCK_CACHE_PREFIX = 'stock:';
const STOCK_CACHE_TTL = 300; // 5分钟
// 分布式锁
const LOCK_PREFIX = 'lock:';
const LOCK_TTL = 10; // 10秒
// 用户限流
const RATE_LIMIT_PREFIX = 'rate_limit:';
const RATE_LIMIT_TTL = 1; // 1秒
```
### 缓存策略
1. **多级缓存**
- CDN缓存静态资源
- Redis缓存热点数据
- 本地缓存减少网络IO
2. **缓存更新策略**
- 主动更新:秒杀开始前预加载
- 异步更新:异步刷新数据库
- 失效策略设置合理的TTL
3. **缓存预热**
- 秒杀开始前加载商品信息
- 预热库存信息到Redis
- 预加载热门商品
### 分布式锁实现
```java
public boolean acquireDistributedLock(String lockKey, String requestId, long expireTime) {
String result = redisTemplate.opsForValue().set(
lockKey,
requestId,
expireTime,
TimeUnit.MILLISECONDS
);
return "OK".equals(result);
}
public boolean releaseDistributedLock(String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
"return redis.call('del', KEYS[1]) " +
"else " +
"return 0 " +
"end";
Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
Collections.singletonList(lockKey),
requestId);
return result != null && result > 0;
}
```
## 扩展性考虑
### 1. 水平扩展
- **无状态服务**:服务实例可以水平扩展
- **数据分片**按商品ID分片
- **读写分离**:主库写入,从库读取
### 2. 垂直扩展
- **服务拆分**:按业务域拆分微服务
- **数据分层**:热数据、温数据、冷数据分离
- **缓存层扩展**Redis集群扩容
### 3. 异步处理
- **消息队列**:订单处理异步化
- **事件驱动**:使用事件总线
- **最终一致性**:保证数据最终一致
### 4. 容灾备份
- **多活架构**:多机房部署
- **故障转移**:自动故障检测和转移
- **数据备份**:定时备份和实时同步
## 实际项目经验
### 1. 技术栈选择
- **前端**Vue.js + React
- **后端**Spring Boot + Node.js
- **数据库**MySQL + Redis
- **缓存**Redis Cluster
- **消息队列**Kafka
- **监控**Prometheus + Grafana
### 2. 性能优化
- **JVM调优**调整堆大小和GC策略
- **MySQL优化**索引优化、慢SQL优化
- **Redis优化**:集群扩容、内存优化
- **网络优化**:连接池配置、超时设置
### 3. 运维部署
- **容器化**Docker + Kubernetes
- **CI/CD**Jenkins + GitLab
- **监控告警**ELK Stack + AlertManager
- **压测工具**JMeter + Locust
### 4. 灰度发布
- **蓝绿部署**:无缝切换
- **金丝雀发布**:逐步放量
- **流量控制**:按比例分配流量
## 阿里P7加分项
### 1. 架构设计能力
- **高可用架构**设计99.99%可用性的系统
- **高性能架构**支持百万级QPS
- **高扩展架构**:支持弹性扩缩容
### 2. 技术深度
- **分布式事务**Seata、TCC、Saga
- **分布式缓存**Redis集群、一致性哈希
- **分布式锁**Redis、Zookeeper、Etcd
### 3. 业务理解
- **电商业务**:理解秒杀业务场景
- **用户行为**:分析用户抢购习惯
- **风控系统**:防刷、防作弊机制
### 4. 团队管理
- **技术团队**带领10人+技术团队
- **项目管控**:管理千万级用户项目
- **技术方案评审**:评审核心技术方案
### 5. 前沿技术
- **Serverless**:秒杀函数化
- **云原生**K8s微服务架构
- **AI应用**:智能推荐、风控
## 面试常见问题
### 1. 秒杀系统如何防止超卖?
- 使用Redis预减库存
- 分布式锁控制并发
- 数据库唯一约束
- 消息队列异步处理
### 2. 如何实现限流策略?
- 令牌桶算法
- 漏桶算法
- Redis计数器
- Nginx限流模块
### 3. 分布式锁的实现方式?
- Redis RedLock
- Zookeeper
- Etcd
- 数据库悲观锁
### 4. 如何保证数据一致性?
- 最终一致性
- 消息队列补偿
- 定时任务对账
- 幂等性设计
### 5. 秒杀系统的瓶颈在哪里?
- 库存查询
- 下单逻辑
- 支付处理
- 库存同步

View File

@@ -0,0 +1,166 @@
# 系统设计方法论
## 问题
1. 系统设计的核心原则是什么?
2. 如何进行需求分析?
3. 如何估算系统容量?
4. 数据模型设计有哪些最佳实践?
5. 如何设计高可用架构?
---
## 标准答案
### 1. 系统设计原则
**核心原则**
1. **简单性**KISSKeep It Simple, Stupid
2. **模块化**(高内聚、低耦合)
3. **可扩展性**(水平扩展、垂直扩展)
4. **高可用性**(冗余、故障隔离)
5. **一致性**CAP 理论权衡)
---
### 2. 需求分析
**功能需求**
- 系统做什么?
- 用户角色有哪些?
- 核心流程是什么?
**非功能需求**
- **性能**QPS、响应时间
- **可用性**99.9%、99.99%、99.999%
- **扩展性**:支持多少用户
- **安全性**:认证、授权、加密
- **一致性**:强一致、最终一致
---
### 3. 容量估算
**QPS 估算**
```
日活用户DAU100 万
平均每人每天请求20 次
总 QPS = 100 万 × 20 / 86400 ≈ 231 QPS
峰值 QPS = 231 × 5 ≈ 1155 QPS假设峰值是平均的 5 倍)
```
**存储估算**
```
用户数100 万
每人平均数据1 KB
总存储 = 100 万 × 1 KB ≈ 1 GB
每年增长 = 1 GB × 12 = 12 GB
```
**带宽估算**
```
平均响应大小10 KB
QPS1000
带宽 = 1000 × 10 KB × 8 = 80 Mbps
```
---
### 4. 数据模型设计
**原则**
1. **范式化**(减少冗余)
2. **反范式化**(提高性能)
3. **分区**(水平、垂直)
4. **索引**(加速查询)
**示例**
```sql
-- 范式化3NF
CREATE TABLE users (
id BIGINT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT,
amount DECIMAL(10,2),
created_at DATETIME,
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 反范式化(冗余用户名,避免 JOIN
CREATE TABLE orders_denormalized (
id BIGINT PRIMARY KEY,
user_id BIGINT,
user_name VARCHAR(50), -- 冗余
amount DECIMAL(10,2),
created_at DATETIME
);
```
---
### 5. 高可用架构
**冗余设计**
```
┌─────────────┐
│ 负载均衡 │ (Nginx、HAProxy)
└──────┬──────┘
┌─────────┼─────────┐
│ │ │
┌──▼──┐ ┌──▼──┐ ┌──▼──┐
│App 1│ │App 2│ │App 3│
└──┬──┘ └──┬──┘ └──┬──┘
│ │ │
└─────────┼─────────┘
┌──────▼──────┐
│ 主从数据库 │
│ Master │
│ Slave │
└─────────────┘
```
**故障隔离**
- 熔断器Circuit Breaker
- 限流Rate Limiter
- 降级Fallback
- 舱舱模式Bulkhead
---
### 6. 扩展性设计
**垂直扩展Scale Up**
- 升级硬件CPU、内存、磁盘
- 简单、快速
- 有上限(硬件限制)
**水平扩展Scale Out**
- 增加机器数量
- 无限扩展
- 需要架构支持(无状态、数据分片)
---
### 7. 阿里 P7 加分项
**架构思维**
- 能进行技术选型(权衡各种方案)
- 能进行容量规划(预估资源需求)
- 能进行成本控制(性价比优化)
**设计能力**
- 能设计高并发架构
- 能设计高可用架构
- 能设计可扩展架构
**沟通能力**
- 能清晰地表达设计方案
- 能进行技术方案评审
- 能推动方案落地