diff --git a/IM-%E7%B3%BB%E7%BB%9F%E6%B6%88%E6%81%AF%E5%AD%98%E5%82%A8%E4%B8%8E%E6%8E%A8%E9%80%81%E7%AD%96%E7%95%A5%E6%96%87%E6%A1%A3.md b/IM-%E7%B3%BB%E7%BB%9F%E6%B6%88%E6%81%AF%E5%AD%98%E5%82%A8%E4%B8%8E%E6%8E%A8%E9%80%81%E7%AD%96%E7%95%A5%E6%96%87%E6%A1%A3.md new file mode 100644 index 0000000..b76cd49 --- /dev/null +++ b/IM-%E7%B3%BB%E7%BB%9F%E6%B6%88%E6%81%AF%E5%AD%98%E5%82%A8%E4%B8%8E%E6%8E%A8%E9%80%81%E7%AD%96%E7%95%A5%E6%96%87%E6%A1%A3.md @@ -0,0 +1,141 @@ +# 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` 表 +- 支持离线同步 \ No newline at end of file