# IM 服务端架构与新功能开发指南 > 文档状态:按 2026-09-08 代码实现整理 > 适用项目:`im_server` > 文档目标:让新接手的开发者能够快速判断一个功能应放在哪里、如何调用、如何存储、如何做多节点一致性,以及如何验收。 ## 1. 系统定位 `im_server` 是基于 Tinode 扩展的多租户 IM 业务服务,同时承担两类职责: 1. IM 实时核心:WebSocket 连接、登录会话、Topic 订阅、消息路由、在线状态、音视频信令。 2. C 端产品业务:注册、安全、好友、群治理、收藏、文件、工作台、会议、日报、举报等 HTTP API。 系统不是传统的 `controller -> service -> repository` 三层单体。它的核心是“Topic Actor 实时模型 + HTTP 业务扩展层 + Store 统一持久化边界”。开发新功能时必须先判断它属于实时 Topic 链路,还是 HTTP 业务链路,或者同时涉及两者。 ## 2. 系统边界 ### 2.1 服务与数据库归属 | 服务 | 直连数据库 | 负责数据 | | --- | --- | --- | | IM Server | 租户业务库,默认库为 `tinode` | 用户、认证、Topic、订阅、私聊/群聊消息、群业务、好友关系、文件元数据、C 端业务数据 | | Admin / HotGo | `hotgo` | 租户注册表、系统配置、字典、后台账号、菜单权限、后台命令 Outbox、管理端摘要数据 | 原则:服务与库一一对应,Admin 不直连租户库,IM 不直连 `hotgo`。跨系统写操作通过 Kafka 命令/事件,必须同步返回的少量查询通过受控的内部 HTTP API。 ### 2.2 租户隔离 目标模型是“一个租户一个业务库”: - `tenant_id` 是请求上下文和路由键,不要因为租户库内没有 `tenant_id` 列就在代码中丢掉租户上下文。 - 所有业务 Store 调用必须显式传递 `types.TenantID`。 - `store.ForTenant` 和 `tenantBusinessAdapter` 负责验证租户与选择租户适配器。 - MySQL 的 `TenantRoutedAdapter.TenantAdapterFor` 负责将租户路由到对应连接池。 - 任何无租户上下文的业务查询都应失败关闭,不允许回退到旧的无租户查询。 ## 3. 技术栈 | 领域 | 当前实现 | 用途 | | --- | --- | --- | | 语言 | Go 1.26 | 服务端主体 | | 实时协议 | Tinode JSON Protocol、WebSocket、Long Polling、gRPC | 长连接、Topic 订阅、消息和集群通信 | | HTTP | `net/http` + `http.ServeMux` | C 端 REST API、文件 API、内部 API | | 数据库 | MySQL + `database/sql` + `sqlx` | 租户业务最终状态 | | 热状态/缓存 | Redis 7,`go-redis/v9` | 在线状态、Seq、幂等、群热消息、对象缓存、关系 Set、限流、跨节点 fanout | | 异步事件 | Kafka,`segmentio/kafka-go` | 跨系统命令、消息异步持久化、审计、缓存失效、失败重试与死信 | | 文件 | 阿里云 OSS,保留 FS/S3 适配器 | 文件对象存储,业务库只存元数据和引用 | | 文件安全 | 阿里云内容安全 | 上传完成后的异步审核 | | 离线推送 | JPush,同时保留 FCM/TNPG 插件能力 | 离线提醒;客户端重连后按 Topic seq 补偿 | | 音视频 | Tinode 通话信令 + 声网 RTC Token | 呼叫邀请/接听/挂断与 RTC 加入 | | 认证 | basic/token/code/rest 可插拔认证器 | 密码、Token、验证码和外部认证 | | 可观测性 | Go `log`、expvar、Prometheus exporter、pprof | 日志、运行指标和性能诊断 | ## 4. 运行时架构 ```text Client |-- WebSocket /v0/channels | -> Session -> Hub -> Topic actor -> Store/Redis | |-> local sessions | `-> Redis fanout -> other IM nodes -> WebSocket | |-- HTTP /v1/im/* | -> protocol middleware -> bearer/API key/tenant | -> handler -> Store mapper -> tenant adapter -> tenant MySQL | |-> Redis cache/short state | `-> business event -> online WebSocket/Kafka | `-- Upload/Download -> media handler -> OSS -> file metadata/link -> tenant MySQL `-> file security task -> Kafka -> Aliyun security Admin / HotGo |-- Kafka admin command/config event -> IM consumer -> tenant business mutation `-- signed internal HTTP <-------> IM internal read API ``` ### 4.1 启动顺序 `server/main.go` 是服务入口,主要顺序为: 1. 读取 JSON with comments 格式的 `meetingim.conf`/`tinode.conf`。 2. 初始化日志、expvar、pprof 和集群 worker ID。 3. 打开 Store,校验数据库版本与租户适配能力,同时初始化 Redis runtime。 4. 初始化 Kafka、IM 内部 API 和 Admin 内部配置 API 客户端。 5. 初始化认证器、验证器、文件处理器、Push 和音视频。 6. 创建 `SessionStore` 和 `Hub`,启动 Redis 群消息 fanout 订阅。 7. 启动 Kafka Admin Command、Config Event、Cache Invalidate、Message Persist 和 Dead Letter 消费者。 8. 启动集群、gRPC、HTTP/WebSocket 路由和优雅退出。 任何新增的基础组件都应明确放在这个顺序中,初始化失败时应快速终止启动,不要让必需依赖在不可用状态下继续运行。 ## 5. 核心业务模型 ### 5.1 Session `Session` 表示一条客户端连接,保存租户、用户、设备、认证等级、已订阅 Topic 和输出队列。一个用户可以同时有多个 Session。 登录和断线时需同步 Redis 在线状态;心跳用于刷新 presence TTL。不应仅依赖本进程 Session 判断全局在线状态。 ### 5.2 Hub `Hub` 是 Topic 路由中心,核心通道包括: | 通道 | 用途 | | --- | --- | | `join` | 加载/创建 Topic,将 Session 附加到 Topic | | `routeCli` | 客户端消息路由到 Topic | | `routeSrv` | 服务端业务消息路由到 Topic/Session | | `meta` | 未订阅 Topic 的元数据查询 | | `unreg` | 卸载或删除 Topic | | `userStatus` | 用户停用/恢复等状态变更 | Topic 索引不是纯字符串,而是 `types.TopicKey{TenantID, Topic}`,以防止不同租户的同名 Topic 串数据。 ### 5.3 Topic Actor `Topic` 是会话和消息处理单元,通过 channel 串行处理加入、退出、客户端消息、服务端消息和元数据操作。主要分类包括: | Topic | 含义 | | --- | --- | | `me` | 用户主 Topic,会话列表和用户级 presence | | `fnd` | 搜索/发现 Topic | | `usr...` | 客户端可见的 P2P 对端标识,入库前需归一化为真实 P2P Topic | | `grp...` | 群聊 Topic | | `chn...` | 频道 Topic | | `slf...` | 个人收藏/保存消息 Topic | | `sys...` | 系统通知 Topic | 涉及消息发送、已读、撤回、编辑、通话信令、在线投递时,优先复用 Topic/Session 链路,不要另造一套无状态 HTTP 投递逻辑。 ## 6. 四类标准调用链路 ### 6.1 WebSocket 实时消息 ```text Client packet -> hdl_websock.go 解码 -> Session 认证/租户上下文 -> Hub.join / Hub.routeCli -> Topic 权限和业务校验 -> Redis 原子 Seq + client_mid 幂等 -> 本地 Session 实时投递 -> Redis Pub/Sub 跨节点 fanout -> Kafka persist 异步落 MySQL ``` 群消息使用 `im_group_messages`,私聊仍使用私聊消息表。`SeqId` 全链路必须使用 `int64/BIGINT`,群 Topic seq 由 Redis 原子递增,数据库只作基线与最终持久化。 群热消息可在 Redis 保留 24 小时左右,历史补偿最终以 MySQL 为准。离线用户只接收 Push 提醒,重连后按 Topic seq 拉取缺口。 ### 6.2 C 端 HTTP 业务请求 ```text /v1/im/* -> withIMHTTPProtocol -> API key + X-IM-Schema + X-Request-ID -> Bearer token -> principal{tenant_id, uid} -> 写请求 Idempotency-Key 中间件 -> serveIM... handler -> store. mapper -> TenantBusinessAdapter -> tenant MySQL / Redis -> writeIMSuccess / writeIMError ``` 所有已认证的 `POST/PUT/PATCH/DELETE` 默认要求 `Idempotency-Key`,幂等结果保留 24 小时。同一 key 使用不同请求体必须返回冲突,已完成请求应重放原响应。 HTTP 统一响应包含 `code/data/reason/message/details/request_id/server_time`。业务错误应返回稳定 `reason`,不应将 SQL 或内部异常直接暴露给客户端。 ### 6.3 Admin 后台写操作 ```text Admin API -> hotgo 本地权限校验 -> 同事务写 command + outbox -> Kafka im.admin.command -> IM consumer 校验 tenant/event/actor -> event_id + consumer_group 幂等抢占 -> 租户库业务变更 -> 缓存失效 + Topic/Session 同步 -> Kafka im.admin.command.result -> Admin 更新命令结果 ``` 不可重试的参数、权限、版本冲突应直接返回稳定失败原因。临时故障按退避策略重试,超过上限写 `im.dead.letter` 和租户失败表。人工重放必须生成新 `event_id`,并使用 `parent_event_id` 串起审计链。 ### 6.4 文件链路 ```text Client request upload -> IM 创建文件元数据 -> OSS 上传/回调完成 -> 租户库更新文件状态 -> 绑定消息/群文件/业务引用 -> Kafka im.file.security -> 阿里云安全检测 -> 更新审核状态并通知用户 ``` 文件字节流不经 Kafka,Kafka 只传递文件 ID、OSS 对象信息和审核任务。任何业务文件都必须建立引用记录,否则垃圾回收可能将它当作孤儿文件删除。 ## 7. 数据分层与一致性 ### 7.1 进程内缓存 适合低频变更、全局或租户级、可短时间最终一致的数据: - 租户基本配置和状态。 - 注册短信开关。 - 字典和第三方配置(OSS、文件安全、短信、JPush、Agora)。 更新来源为定时刷新和 Kafka `im.config.event`/`im.cache.invalidate`。进程内缓存不应与 Redis 重复缓存同一份高频业务对象。 ### 7.2 Redis Redis 用于跨节点共享且高频的数据: - 用户在线状态、Session 和群成员节点索引。 - 群消息原子 `SeqId`、`client_mid` 唯一占位和状态。 - 24 小时左右的群热消息。 - 用户、Topic、Subscription、群设置、群成员、成员分页快照和未读数缓存。 - 好友/黑名单 Set。 - 验证码、Action Token、临时占位、限流等 TTL 状态。 - 群消息 Redis Pub/Sub 跨节点实时 fanout。 Redis key 必须包含统一前缀和租户维度,不允许跨租户共用业务 key。写 MySQL 成功后必须失效或刷新对应 Redis 数据,多节点通过 Kafka 失效事件收敛。 ### 7.3 MySQL MySQL 是最终业务状态、历史查询和审计依据。以下数据不得仅存 Redis: - 用户、凭据、好友、黑名单、Topic、订阅和群治理最终状态。 - 私聊/群聊历史消息、撤回和编辑版本。 - 文件元数据、业务引用和安全审核结果。 - HTTP 幂等结果、Kafka 消费幂等、死信和审计数据。 ### 7.4 一致性顺序 普通业务写的推荐顺序: 1. 校验租户、身份、权限、幂等键和业务版本。 2. 在同一事务中更新 MySQL 业务状态及 outbox(需要可靠事件时)。 3. 提交事务。 4. 失效本节点 Redis/进程内缓存。 5. 投递 Kafka 失效或业务事件,通知其他节点和客户端。 如果业务要求“先实时到达,再异步落库”,则必须先完成 Redis 幂等占位和 seq 分配,投递 Kafka 持久化事件,并为失败准备重试和死信补偿。 ## 8. Kafka 责任边界 | Topic | 主要用途 | | --- | --- | | `im.admin.command` | Admin 到 IM 的业务写命令 | | `im.admin.command.result` | IM 回传命令结果 | | `im.config.event` | 租户、字典、第三方配置变更 | | `im.business.event` | 好友、群、会议、工作台等 C 端业务事件 | | `im.message.persist` | 私聊消息异步落库 | | `im.group.message.persist` | 群聊消息异步落库 | | `im.message.push` | 离线 Push 任务,属增强链路 | | `im.file.security` | 文件安全检测 | | `im.cache.invalidate` | 多节点缓存失效 | | `im.audit.event` | 跨系统审计 | | `im.dead.letter` | 超过重试上限的事件 | Kafka 不用于 WebSocket 建连、验证码、在线状态、实时群消息 fanout、OSS 字节流或必须当场返回结果的查询。 统一 Envelope 至少包含:`event_id`、`trace_id`、`tenant_id/tenant_code`、`source_service`、`target_service`、`event_type`、`biz_type`、`biz_id`、`idempotency_key`、`version`、`occurred_at`、`actor`、`payload`。 ## 9. 代码组织 | 路径 | 职责 | 新功能常见修改 | | --- | --- | --- | | `server/main.go` | 进程入口、组件初始化、HTTP 路由注册 | 新增路由或新基础组件启动 | | `server/session.go` | 连接、登录、请求分发、设备和 Session 状态 | 账号登录或连接级功能 | | `server/hub.go` | Topic 加载与全局消息路由 | 路由、Topic 生命周期 | | `server/topic.go` / `init_topic.go` | Topic actor、权限、订阅和消息处理 | 消息、群权限、Topic 内实时行为 | | `server/datamodel.go` | WebSocket 客户端/服务端协议结构 | 协议字段或服务端推送类型 | | `server/im_http.go` | C 端产品 HTTP API 的路由处理与通用约定 | 大部分 C 端业务入口 | | `server/internal_api.go` | IM 向 Admin 提供的签名内部查询 API | 后台需要同步读取租户数据 | | `server/admin_internal_config.go` | IM 调用 Admin 内部配置 API | IM 需要 hotgo 配置兜底查询 | | `server/kafka_*.go` | Kafka runtime、生产、消费、重试、死信和各业务 handler | 跨系统或异步事件 | | `server/im_business_events.go` | 业务事件持久化与在线投递 | 需主动推给 C 端的状态变更 | | `server/redis_fanout.go` | 群消息跨节点实时投递 | 群大并发/未加载 Topic 投递 | | `server/store/types/` | 业务实体、值对象、查询参数和稳定错误 | 先定义领域数据结构 | | `server/store/store.go` | Store mapper、参数验证、租户边界、缓存编排 | 对 handler 提供统一持久化 API | | `server/store/infrastructure.go` | HTTP 幂等、业务事件、Kafka 幂等/死信 Store | 可靠基础链路 | | `server/store/group_message_runtime.go` | Redis seq、唯一 key、热消息、presence、缓存和限流 | Redis 新 key 或新的 TTL 状态 | | `server/db/adapter.go` | 持久化能力接口 | 新增 Store 数据能力 | | `server/db/mysql/tenant_adapter.go` | MySQL 租户业务 SQL 实现 | 业务 CRUD/事务 | | `server/db/mysql/*_schema.go` | 扩展业务表建表/升级逻辑 | 新表、列、索引 | | `server/media/` | FS/OSS/S3 文件处理插件 | 文件存储能力 | | `server/filesafety/` | 文件安全适配器 | 文件检测能力 | | `server/push/` | 离线 Push 插件 | 厂商 Push 接入 | | `server/auth/` / `server/validate/` | 认证和凭据验证插件 | 登录或验证方式 | | `server/*_test.go` | 单元与链路测试 | handler、Topic、Kafka、Redis 逻辑测试 | | `server/db/mysql/*_test.go` | MySQL schema 和 SQL 回归 | 数据库变更测试 | ## 10. 新功能放置决策 | 问题 | 选择 | | --- | --- | | 是否是客户端建连、订阅、发消息或通话实时信令? | WebSocket + Session/Hub/Topic | | 是否是 C 端业务 CRUD、列表、搜索、设置或审批? | `/v1/im/*` HTTP + Store | | 是否是 Admin 对租户业务的写操作? | Admin 本地 command/outbox + Kafka + IM consumer | | Admin 是否必须当场读取租户详情? | IM 受控内部 GET API | | IM 是否需要读取 hotgo 的低频配置? | 进程内缓存 + Kafka 刷新 + Admin 内部 API 兜底 | | 是否需要跨节点高频共享、TTL 或原子计数? | Redis | | 是否需要最终可追溯的业务状态? | 租户 MySQL | | 是否跨系统、可异步、需重试/削峰/审计? | Kafka | | 是否为在线群消息实时扩散? | Redis Pub/Sub + WS,不用 Kafka 做主链路 | | 是否为文件本体? | OSS;MySQL 只存元数据/引用 | ## 11. 新功能标准开发流程 ### 11.1 需求分析 1. 从前后端对接文档提取请求、响应、权限、状态机、幂等、并发和通知要求。 2. 标出数据归属:`hotgo` 公共数据或租户库业务数据。 3. 选择入口:HTTP、WebSocket、Kafka Admin Command 或内部 API。 4. 列出需要同步的状态:MySQL、Redis、Topic 内存、进程内缓存、C 端推送。 5. 明确失败类型:可重试、不可重试、并发冲突、部分成功和补偿。 ### 11.2 领域与数据库 1. 在 `server/store/types/` 按业务域定义实体、状态常量、查询参数和结果。 2. 在 `server/db/adapter.go` 增加最小必要的租户持久化接口,方法必须携带 `TenantID`。 3. 在 MySQL 适配器实现 SQL;复杂写操作使用事务,状态迁移在 SQL `WHERE` 中校验旧状态/版本。 4. 在对应 `*_schema.go` 添加幂等建表/升级 SQL,为高频查询、唯一幂等键和状态扫描建索引。 5. 在 `server/store/store.go` 增加 mapper,负责参数验证、调用 adapter 和缓存编排;handler 不应直接拼 SQL。 表命名遵循当前租户库风格,类型必须与 Go 全链路一致,尤其是 ID、seq、version 使用 `BIGINT/int64`。面向 JavaScript 客户端的 64 位 ID 优先以字符串输出,避免精度丢失。 ### 11.3 API 或协议层 HTTP 功能: 1. 在 `server/im_http.go` 定义独立 request/response 结构,不要直接暴露数据库 row。 2. 使用 `decodeIMJSONBody`、`authenticateIMHTTPBearer`、`requireIMGroupMember` 等公共函数做解码、认证和权限检查。 3. 在 `server/main.go` 注册具体路由,路由顺序要避免通配前缀吞掉更具体的路径。 4. 使用 `writeIMSuccess`/`writeIMError` 统一输出,新增稳定业务 `reason`。 5. 资源更新需并发保护时使用 version/`If-Match`,不允许用 `version=0` 绕过乐观锁。 WebSocket 功能: 1. 在 `datamodel.go` 增加最小协议字段,考虑 JSON 和 protobuf 转换兼容。 2. 在 Session 做连接级验证,在 Topic 做资源权限与业务状态验证。 3. 所有可重发消息必须有 `client_mid`/业务幂等键。 4. 成功后同时考虑本节点 Session、跨节点 fanout、离线 Push 与历史补偿。 ### 11.4 缓存、事件与审计 1. 对高频读对象选择 cache-aside:先 Redis,miss 后读 MySQL 并回填。 2. 所有写方法列出需失效的 key,包括对象 key、关系 Set、分页快照和未读数。 3. 需可靠异步处理时同事务写 outbox,消费端使用 `event_id + consumer_group` 幂等。 4. 影响管理权限、账号安全、消息内容、文件处置或人工重放的操作要写审计。 5. 业务状态变更需立即告知 C 端时,创建业务事件并通过已认证服务端链路投递,不信任客户端伪造的系统消息。 ### 11.5 测试与文档 每个功能至少覆盖: 1. 正常路径、无认证、跨租户、无权限、资源不存在和方法错误。 2. 重复 `Idempotency-Key`/`client_mid` 不产生重复数据。 3. 同一幂等键配不同 payload 返回冲突。 4. version 冲突和并发状态迁移。 5. MySQL 成功后 Redis/Topic 缓存及在线客户端状态正确刷新。 6. Kafka 重复消费、临时失败重试、不可重试失败和死信重放。 7. 64 位 ID/seq 在 JSON 编解码时不丢失精度。 8. 更新前后端对接文档、SQL 变更集和未实现增强项。 ## 12. 关键约定 ### 12.1 ID 与时间 - 用户 ID 由 Snowflake UID 体系生成,对外使用 `usr...` 编码形式或协议规定的字符串。 - 业务 ID 必须全局或租户内唯一,不能用秒级时间戳直接代替唯一 ID。 - `SeqId`、数据库主键和 version 使用 `int64/BIGINT`。 - 持久化与对外时间使用 UTC,HTTP 输出 RFC3339/RFC3339Nano。 ### 12.2 Topic 归一化 客户端传入的 `usr...`、`slf` 等可见 Topic 不一定是数据库真实 Topic。历史查询、上下文、收藏、转发、媒体、回执等接口在查库前必须统一归一化,并在鉴权、查询和响应之间保持明确的 Topic 语义。 ### 12.3 权限 - HTTP handler 负责验证主体和请求参数,Store/adapter 仍应使用租户和业务条件限制写入。 - Topic 管理员、群主、普通成员权限以服务端为准,不接受客户端声明的角色。 - 群主转让、设管理员、禁言、踢人等变更后,必须刷新 Topic 内 `perUser` 权限快照和 Redis 订阅/成员缓存,不能等待重连后生效。 - 封禁、冻结、踢设备、全端退出和注销等账号治理必须同步处理已存在 Session。 ### 12.4 可观测性 - 日志使用 `server/logs` 的 `Info/Warn/Err`,默认输出 stderr,由容器日志系统收集。 - 日志行前缀为 `I/W/E` 加 Go log flags 生成的日期时间;敏感值、Token、密码、验证码、证件号和第三方密钥不得记录。 - HTTP 日志和异步事件应携带 `request_id/trace_id`、租户、业务类型和业务 ID。 - 新增核心链路应增加请求数、失败数、延迟、队列深度/积压和死信指标。 ## 13. 禁止的实现方式 1. 在 HTTP handler 内直接打开 MySQL 或拼接 SQL。 2. 因租户库表没有 `tenant_id` 列,就不向 Store 传递 `TenantID`。 3. Admin 直连 `tinode` 或 IM 直连 `hotgo`。 4. 将 Kafka 当作 HTTP RPC 或实时 WebSocket fanout 使用。 5. 将业务最终状态只存在 Redis。 6. 为同一份高频数据同时增加进程内缓存和 Redis 缓存。 7. 业务写成功后不失效 Redis、Topic 权限快照和成员分页快照。 8. 重试请求没有 `Idempotency-Key/client_mid/event_id`。 9. 使用 `int` 或 JSON number 承载可能超过 JavaScript 安全范围的 ID/seq。 10. 直接信任客户端构造的系统通知、管理员角色或审计信息。 11. 文件上传成功后不创建业务引用和安全审核任务。 12. 新增数据表只在开发者本机手工执行,不写幂等 schema SQL、升级逻辑和回归测试。 ## 14. 开发与验收命令 MySQL 构建使用 build tag: ```bash go build -tags mysql -o bin/tinode ./server go build -tags mysql -o bin/init-db ./tinode-db ``` 建议测试顺序: ```bash # 先跑修改模块的定向测试 go test ./server -run 'TestName' # Store 与 MySQL schema/adapter go test -tags mysql ./server/store/... ./server/db/mysql/... # 完整服务端回归 go test -tags mysql ./server/... ``` 发版前至少检查: - 配置文件可解析,MySQL、Redis、Kafka、OSS 等必需依赖可连通。 - 数据库版本与代码一致,所有新表/列/索引已在目标环境幂等执行。 - Kafka Topic、消费组、重试和死信链路可用。 - 单节点和多节点下的在线状态、群消息、权限变更均一致。 - 新增接口与前后端对接文档一致,无密钥、密码或测试 Token 进入 Git。 ## 15. 新功能提交清单 开发者在提交 PR/代码前应逐项确认: - [ ] 已确定功能入口是 HTTP、WebSocket、Kafka 还是内部 API。 - [ ] 已确定数据归属 `hotgo` 还是租户库。 - [ ] 所有 Store/adapter 调用都显式携带 `TenantID`。 - [ ] 已设计幂等键、唯一索引、业务版本和状态机。 - [ ] 已明确 MySQL、Redis、进程内缓存的使用和失效顺序。 - [ ] 需跨系统可靠投递时使用 outbox + Kafka,消费端已幂等。 - [ ] 已处理 Topic 内存权限快照和多节点同步。 - [ ] 文件已存 OSS,业务引用和安全审核已建立。 - [ ] `SeqId`/ID/version 已在 Go、JSON、Kafka 和 MySQL 全链路使用 64 位安全类型。 - [ ] 已增加正常、权限、跨租户、幂等、并发、缓存和重试测试。 - [ ] 已补充 API 对接文档、SQL 变更和未完成增强项。 ## 16. 相关文档 - `docs/IM-前后端对接文档.md`:C 端业务 API 和交互协议。 - `docs/IM-系统设计文档.md`:原始产品系统设计。 - `docs/IM-Redis三层数据分层改造方案.md`:进程内、Redis、MySQL 分层细节。 - `docs/IM-Kafka接入方案.md`:Admin/IM 边界、Topic、幂等、重试和死信。 - `docs/IM-Kafka接入范围识别.md`:按业务场景判断 Kafka 接入范围。 - `docs/IM-Kafka接入联调测试文档.md`:Admin 与 IM 联调用例。 - `docs/third/IM-文件安全第三方接入记录.md`:OSS 和文件安全链路。 - `docs/IM-未实现后续增强项.md`:已知未完成能力和深度优化项。