1 IM 系统消息存储与推送策略文档
西街长安 edited this page 2026-01-30 21:37:29 +08:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

IM 系统消息存储与推送策略文档

1. 概述

本策略文档定义了 消息在系统中的存储、读取和推送流程,目标是:

  • 保证 消息实时性
  • 支持 离线消息存储与同步
  • 支持 多端登录同步
  • 支持 单聊、群聊及系统消息

2. 消息存储策略

2.1 消息表设计

表结构参考前期设计:

表名 作用
Messages 存储所有聊天消息(单聊/群聊)
Conversation 缓存用户最近会话信息last_message_id, target_id, unread_count
Files 附件 / 图片 / 语音存储URL

2.2 消息存储规则

  1. 单聊消息
    • 写入 Messages
    • 更新发送者和接收者 Conversation
    • 更新 UnreadCount
  2. 群聊消息
    • 写入 Messages
    • 更新群成员对应的 Conversationexcept 发送者)
    • 更新每个成员的 UnreadCount
  3. 文件消息
    • 文件存储到对象存储OSS/S3/MinIO
    • Messages.Content 存文件 URL + metadata
  4. 消息撤回
    • 消息允许撤回时,修改 `message.status = 1
    • 更新 Conversation.LastMessageId(如撤回的是最后一条消息)

3. 消息推送策略

3.1 推送原则

  • 实时性:在线用户立即通过 WebSocket 推送
  • 可靠性:离线用户存储消息,登录时同步
  • 顺序保证:消息按 timestampmessageId 顺序发送
  • 幂等性:客户端可根据 messageId 去重

3.2 单聊推送流程

  1. 发送者通过 WebSocket 或 HTTP API 发送消息
  2. 服务端写入 Messages
  3. 查询接收者是否在线
    • 在线:通过 WebSocket 推送
    • 离线:存储到 Redis 或 Conversation.UnreadCount
  4. 接收者收到消息后发送 MESSAGE_ACK
  5. //暂不要求:更新消息状态(已送达 / 已读)

3.3 群聊推送流程

  1. 发送者发送群消息
  2. 服务端写入 Messages 表
  3. 查询群成员列表(GroupMember 表)
  4. 遍历成员:
    • 在线成员WebSocket 推送
    • 离线成员:增加 UnreadCount,保存在 Redis/数据库
  5. //暂不要求:接收者回 ACK 后更新 message_receipt(已读)

3.4 离线消息处理

  • 离线消息存储位置:
    1. 数据库 Messages 表(长期保存)
    2. Redis 缓存(短期加速推送)
  • 客户端上线时:
    1. 请求 /syncMessages 接口
    2. 返回未读消息 + 未读计数
  • 消息同步完成后清除缓存或更新状态

3.5 多端同步策略

  • 每个设备维护独立的 deviceId
  • WebSocket 推送时:
    • 排除发送设备
    • 推送给同账号其他设备
  • //暂不要求:消息回执:
    • 每端发送 ACK
    • 服务端更新 Voncersmessage_receipt

4. 消息可靠性保障

场景 解决方案
消息丢失 发送端生成 requestId,服务端去重
消息顺序错乱 messageIdtimestamp 排序
WebSocket 异常断开 客户端重连后同步离线消息
群聊大消息量 异步推送 + 批量 ACK

5. //暂不要求:高性能优化策略

  1. 消息表索引(chat_type, to_id, created_at)
  2. 会话表缓存conversation 表避免全表查询
  3. Redis 缓存:用户在线状态、未读消息数
  4. 分表/分库:按月或按用户分表
  5. 异步推送队列:消息通过 MQKafka/RabbitMQ推送保证高并发

6. 消息撤回与删除策略

  1. 撤回条件:超时限制( 2 分钟内可撤回)
  2. 撤回操作
    • 更新 message.status = 1
    • 更新 Conversation.LastMessageId
    • 推送撤回事件到在线用户

7. 系统消息与通知策略

  • 系统消息(好友申请、群邀请、公告)走 同样的消息推送流程
  • 保留在 Notification
  • 支持离线同步