# 即时通讯系统设计 ## 需求分析和数据量评估 ### 需求分析 - **核心功能**:单聊、群聊、消息推送、在线状态 - **业务场景**:社交应用、企业通讯、客服系统 - **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 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 - **缓存优化**:推送结果缓存