# IM 系统消息存储与推送策略文档 ## 1. 概述 本策略文档定义了 **消息在系统中的存储、读取和推送流程**,目标是: - 保证 **消息实时性** - 支持 **离线消息存储与同步** - 支持 **多端登录同步** - 支持 **单聊、群聊及系统消息** ------ ## 2. 消息存储策略 ### 2.1 消息表设计 表结构参考前期设计: | 表名 | 作用 | | ------------ | ------------------------------------------------------------ | | Messages | 存储所有聊天消息(单聊/群聊) | | Conversation | 缓存用户最近会话信息(last_message_id, target_id, unread_count) | | Files | 附件 / 图片 / 语音存储URL | ------ ### 2.2 消息存储规则 1. **单聊消息** - 写入 `Messages` 表 - 更新发送者和接收者 `Conversation` 表 - 更新 `UnreadCount` 2. **群聊消息** - 写入 `Messages` 表 - 更新群成员对应的 `Conversation` 表(except 发送者) - 更新每个成员的 `UnreadCount` 3. **文件消息** - 文件存储到对象存储(OSS/S3/MinIO) - `Messages.Content` 存文件 URL + metadata 4. **消息撤回** - 消息允许撤回时,修改 `message.status = 1 - 更新 `Conversation.LastMessageId`(如撤回的是最后一条消息) ------ ## 3. 消息推送策略 ### 3.1 推送原则 - **实时性**:在线用户立即通过 WebSocket 推送 - **可靠性**:离线用户存储消息,登录时同步 - **顺序保证**:消息按 `timestamp` 或 `messageId` 顺序发送 - **幂等性**:客户端可根据 `messageId` 去重 ------ ### 3.2 单聊推送流程 1. 发送者通过 WebSocket 或 HTTP API 发送消息 2. 服务端写入 `Messages` 表 3. 查询接收者是否在线 - **在线**:通过 WebSocket 推送 - **离线**:存储到 Redis 或 `Conversation.UnreadCount` 4. 接收者收到消息后发送 `MESSAGE_ACK` 5. //暂不要求:更新消息状态(已送达 / 已读) ------ ### 3.3 群聊推送流程 1. 发送者发送群消息 2. 服务端写入 `Message`s 表 3. 查询群成员列表(`GroupMember` 表) 4. 遍历成员: - **在线成员**:WebSocket 推送 - **离线成员**:增加 `UnreadCount`,保存在 Redis/数据库 5. //暂不要求:接收者回 ACK 后更新 `message_receipt`(已读) ------ ### 3.4 离线消息处理 - 离线消息存储位置: 1. 数据库 `Messages` 表(长期保存) 2. Redis 缓存(短期加速推送) - 客户端上线时: 1. 请求 `/syncMessages` 接口 2. 返回未读消息 + 未读计数 - 消息同步完成后清除缓存或更新状态 ------ ### 3.5 多端同步策略 - 每个设备维护独立的 `deviceId` - WebSocket 推送时: - 排除发送设备 - 推送给同账号其他设备 - //暂不要求:消息回执: - 每端发送 ACK - 服务端更新 `Voncers` 和 `message_receipt` ------ ## 4. 消息可靠性保障 | 场景 | 解决方案 | | ------------------ | ---------------------------------- | | 消息丢失 | 发送端生成 `requestId`,服务端去重 | | 消息顺序错乱 | 按 `messageId` 或 `timestamp` 排序 | | WebSocket 异常断开 | 客户端重连后同步离线消息 | | 群聊大消息量 | 异步推送 + 批量 ACK | ------ ## 5. //暂不要求:高性能优化策略 1. **消息表索引**:`(chat_type, to_id, created_at)` 2. **会话表缓存**:`conversation` 表避免全表查询 3. **Redis 缓存**:用户在线状态、未读消息数 4. **分表/分库**:按月或按用户分表 5. **异步推送队列**:消息通过 MQ(Kafka/RabbitMQ)推送,保证高并发 ------ ## 6. 消息撤回与删除策略 1. **撤回条件**:超时限制( 2 分钟内可撤回) 2. **撤回操作**: - 更新 `message.status = 1` - 更新 `Conversation.LastMessageId` - 推送撤回事件到在线用户 ------ ## 7. 系统消息与通知策略 - 系统消息(好友申请、群邀请、公告)走 **同样的消息推送流程** - 保留在 `Notification` 表 - 支持离线同步