Java SpringBoot 即时通讯源码系统设计与 Redis 缓存部署架构
1. 项目背景与技术选型目标
IM即时通讯APP的研发重点,不只是完成聊天页面和消息发送按钮,而是设计一套能够支撑实时连接、用户关系、消息存储、群组协作、多端同步和业务扩展的通信系统。类似微信的IM产品,前端展示的是好友列表、会话窗口、群聊页面、朋友圈、红包、语音通话、视频通话、文件发送等功能;后端实际需要处理长连接接入、协议解析、消息路由、ACK确认、离线消息补偿、历史消息查询、群聊扩散、未读数计算、权限校验、缓存更新和集群部署等工程问题。
整体技术方案可以采用uniapp、Vue2、Java SpringBoot、MySQL 5.7+和Redis组合。移动端和H5端使用uniapp,PC端使用Vue2,后端业务服务使用Java SpringBoot,结构化数据存储在MySQL中,在线状态、连接路由、未读数、群成员缓存等高频数据通过Redis处理。
从系统设计角度看,IM功能模块之间并不是孤立存在的。好友、单聊、群聊、群管理、消息撤回、已读未读、表情、自定义表情、文件发送、收藏、名片分享等功能,都依赖统一的账号体系、关系链模型、会话模型和消息协议。红包、钱包、朋友圈、语音通话、视频通话、多人语音会议、i18n多语言等模块,则是在基础通信能力稳定后继续扩展出的业务能力。
在技术选型阶段,研发团队需要重点关注几个问题:通信协议如何设计,Socket、WebSocket和HTTP如何分工;消息格式是否便于扩展,JSON结构如何兼容不同消息类型;消息如何保证可靠投递,ACK、重试、去重和离线补偿如何处理;群聊消息如何分发,写扩散、读扩散或混合模式如何选择;四端登录时,安卓、iOS、H5和PC端的消息状态如何同步;部署时,连接服务、业务服务、MySQL和Redis如何拆分。
因此,设计即时通讯APP时,应先明确底层通信链路、消息结构、会话结构、用户关系、群组关系、缓存边界和数据持久化方式,再逐步展开具体功能模块。这样可以避免前期只围绕页面功能开发,后期在多端同步、群聊扩展、消息可靠性和数据一致性上出现较高改造成本。

2. 技术栈总览
| 层级 | 技术选型 | 主要作用 |
|---|---|---|
| 移动端 / H5 | uniapp | 支持安卓、iOS、H5多端页面开发 |
| PC端 | Vue2 | 构建桌面端聊天、联系人、群组、文件等界面 |
| 后端 | Java SpringBoot | 处理用户、好友、群、消息、钱包、朋友圈等业务接口 |
| 数据库 | MySQL 5.7+ | 存储用户、关系链、群组、消息索引、钱包流水等结构化数据 |
| 缓存 | Redis | 存储在线状态、连接路由、未读数、群成员缓存、分布式锁等 |
| 通信协议 | Socket / WebSocket / HTTP | 分别承载APP长连接、浏览器实时通信和普通业务接口 |
| 安全传输 | SSL / TLS | 保护登录、消息、钱包、文件等传输数据 |
3. 系统分层设计
从工程结构上看,一个即时通讯APP可以拆成以下几个核心层级。
3.1 终端展示层
终端层主要包含安卓、iOS、H5和PC端。移动端与H5端采用uniapp,PC端采用Vue2。
终端层需要处理的内容包括:
- 会话列表渲染
- 单聊和群聊消息气泡
- 文本、图片、语音、视频、文件消息展示
- 表情和自定义表情面板
- 红包消息卡片
- 名片消息卡片
- 消息撤回状态
- 引用消息展示
- @群成员提醒
- 未读数展示
- 朋友圈动态流
- 钱包和红包记录页面
- 多语言文本切换
IM前端页面的复杂度通常高于普通业务系统,因为消息状态会频繁变化。比如一条消息可能经历“发送中、发送成功、发送失败、已送达、已读、已撤回”等状态,前端需要维护本地消息列表和服务端消息状态之间的一致性。
3.2 接入通信层
通信层负责处理实时连接。系统可以支持一端口可插拔多协议,包括Socket自定义IM协议、WebSocket和HTTP。
Socket自定义协议适合APP端长连接通信,WebSocket适合H5和PC端,HTTP适合用户资料、好友列表、群资料、朋友圈、钱包流水、收藏记录等普通接口。
通信层通常需要处理:
- 用户连接鉴权
- 心跳检测
- 断线重连
- 消息解包与编码
- 连接路由维护
- 用户在线状态维护
- 消息ACK确认
- 协议适配与转发
连接建立后,服务端可以将用户ID、设备ID、连接ID、节点ID和协议类型写入Redis。这样在消息投递时,可以根据用户在线状态判断是实时投递还是写入离线消息。
4. 消息协议设计
IM系统中,消息格式建议保持简洁,使用JSON结构可以降低多端解析成本,也便于后续扩展新的消息类型。
示例:普通文本消息结构可以设计如下:
{
"cmd": "chat",
"msgId": "202606151800000001",
"conversationId": "single_10001_10002",
"fromUserId": "10001",
"toId": "10002",
"chatType": "single",
"msgType": "text",
"content": {
"text": "这是一条文本消息"
},
"clientSeq": 12,
"serverSeq": 1024,
"sendTime": 1781517600000
}
字段说明:
| 字段 | 含义 |
| cmd | 消息命令,例如chat、ack、revoke、read |
| msgId | 全局唯一消息ID |
| conversationId | 会话ID |
| fromUserId | 发送人ID |
| toId | 接收人ID或群ID |
| chatType | 聊天类型,single表示单聊,group表示群聊 |
| msgType | 消息类型,例如text、image、file、red_packet |
| content | 消息正文 |
| clientSeq | 客户端本地序号 |
| serverSeq | 服务端递增序号 |
| sendTime | 消息发送时间 |
对于图片、文件、红包、名片、引用消息等类型,可以在msgType和content中扩展。
5. 消息可靠性流程
消息可靠性是IM系统的核心能力。一个基础流程可以拆成以下几步:
- 客户端生成本地消息,状态为“发送中”
- 客户端通过长连接发送消息到服务端
- 服务端校验用户身份、会话关系和消息格式
- 服务端生成全局消息ID和服务端序号
- 服务端写入消息存储
- 服务端返回发送ACK
- 接收方在线时实时投递
- 接收方离线时进入离线消息范围
- 接收方上线后同步离线消息
- 接收方阅读后回传已读回执
示例:前端WebSocket接收消息与ACK确认逻辑:
const ws = new WebSocket("wss://im.example.com/ws");
ws.onopen = () => {
ws.send(JSON.stringify({
cmd: "auth",
token: "login-token",
deviceId: "pc-10001"
}));
};
ws.onmessage = (event) => {
const packet = JSON.parse(event.data);
if (packet.cmd === "chat") {
appendMessage(packet.data);
sendAck(packet.data.msgId);
}
if (packet.cmd === "revoke") {
updateMessageRevokeStatus(packet.data.msgId);
}
if (packet.cmd === "read") {
updateMessageReadStatus(packet.data.conversationId);
}
};
function sendAck(msgId) {
ws.send(JSON.stringify({
cmd: "ack",
msgId,
ackTime: Date.now()
}));
}
这里的ACK不是简单的前端提示,而是消息可靠性链路的一部分。服务端可以根据ACK状态判断消息是否成功投递,客户端也可以根据服务端ACK更新消息状态。

6. 好友模块设计
宠友IM好友模块是关系链基础。常见功能包括添加好友、好友申请、同意申请、拒绝申请、删除好友、拉黑、修改备注、查看资料、名片分享等。
好友关系建议采用双向关系表设计。用户A添加用户B后,可以生成两条关系记录,分别用于A查看B、B查看A。这样在查询联系人列表时效率更高,也方便处理备注、黑名单、删除关系等独立状态。
扫一扫添加好友可以通过二维码中的短码、临时票据或加密字符串完成,不建议直接暴露数据库主键。服务端解析二维码内容后,再返回用户资料或好友申请页面。
7. 单聊模块设计
单聊是点对点通信。它需要支持文本、图片、语音、视频、文件、表情、红包、名片、引用消息等多种消息类型。
单聊技术重点包括:
- 会话ID生成规则
- 消息ID生成规则
- 离线消息同步
- 历史消息分页
- 消息去重
- 多端同步
- 已读回执
- 消息撤回
- 文件消息权限校验
历史消息分页建议使用游标方式,例如基于serverSeq或msgId向前查询,不建议只使用页码分页。因为IM消息是实时写入的,页码分页容易因为新消息插入导致数据重复或遗漏。
8. 群聊与群管理模块设计
群聊比单聊复杂,主要难点在于群成员管理、消息扩散、权限判断和未读统计。
群管理功能包括:
- 创建群
- 修改群名称
- 修改群头像
- 群公告
- 群二维码
- 邀请成员
- 移除成员
- 设置管理员
- 转让群主
- 群禁言
- 入群审核
- 扫一扫加入群聊
群成员表可以参考如下结构:
CREATE TABLE im_group_member (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
group_id BIGINT NOT NULL COMMENT '群ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
role TINYINT NOT NULL DEFAULT 0 COMMENT '0成员 1管理员 2群主',
group_nickname VARCHAR(64) DEFAULT NULL COMMENT '群内昵称',
mute_until BIGINT DEFAULT 0 COMMENT '禁言截止时间',
join_time BIGINT NOT NULL COMMENT '加入时间',
status TINYINT NOT NULL DEFAULT 1 COMMENT '1正常 2已移除 3主动退出',
UNIQUE KEY uk_group_user (group_id, user_id)
);
群消息发送时,服务端需要先判断用户是否属于该群、群是否有效、用户是否被禁言。校验通过后,再写入群消息表并进行消息分发。
对于小群,可以采用写扩散方式,为每个成员生成消息收件记录。对于大群,可以采用读扩散或混合模式,减少写入压力。实际项目中可以根据群规模、消息频率和查询性能进行选择。
9. @群成员、引用回复与名片分享
@群成员功能可以在消息体中保存被@用户ID列表,例如:
{
"msgType": "text",
"content": {
"text": "@张三 请确认一下文件内容",
"atUserIds": ["10003"]
}
}
客户端根据atUserIds进行高亮显示,被@用户可以在会话列表中看到特殊提醒。
消息引用和回复适合解决群聊上下文混乱的问题。消息体中可以保存原消息ID、原发送人、原消息摘要等字段。即使原消息内容较长,引用区域也可以只展示摘要。
名片分享可以作为一种特殊消息类型。消息体中保存被分享用户的ID、昵称、头像快照。接收方点击名片后,再通过用户接口查询最新资料。
10. 红包与钱包模块设计
红包和钱包属于资金相关模块,技术设计需要更关注一致性和流水可追踪。
红包功能包括:
- 单聊红包
- 群红包
- 普通红包
- 拼手气红包
- 红包领取记录
- 红包过期退回
- 红包状态查询
钱包功能包括:
- 余额
- 冻结金额
- 充值记录
- 提现记录
- 交易流水
- 红包收支记录
群红包领取属于高并发场景。服务端需要防止重复领取、超额领取和并发扣减异常。常见处理方式是使用Redis原子操作或分布式锁控制领取流程,最终将领取记录和钱包流水落入MySQL。
钱包流水表需要记录交易类型、交易方向、金额、交易前余额、交易后余额、关联业务ID、创建时间等字段。这样可以保证每一笔余额变化都有来源可追踪。
11. 消息撤回、已读未读与多端同步
消息撤回需要服务端校验消息归属、发送人身份、撤回时间范围和消息类型。撤回成功后,服务端向相关用户发送撤回通知,客户端将原消息替换为“该消息已撤回”状态。
已读未读可以分为单聊和群聊两种处理方式。
单聊中,可以记录双方最后已读消息游标。
群聊中,如果逐条记录每个成员的已读状态,数据量会比较大。更常见的做法是记录每个成员在群内的最后已读serverSeq,再通过消息序号计算未读数量。
多端同步需要处理同一账号在手机、H5、PC同时在线的情况。例如用户在PC端读完一个会话后,手机端也应该同步清除未读数。实现上可以将同账号下不同设备都注册到连接路由中,消息状态变化时向其他设备广播同步事件。

12. 表情、自定义表情、文件发送与收藏
表情模块可以分为系统表情和自定义表情。系统表情一般内置在前端资源中,自定义表情需要后端保存图片地址、排序、状态和所属用户。
文件发送需要处理上传、存储、消息发送和下载权限。文件消息体中可以保存文件名、文件大小、文件类型、文件URL、文件hash等信息。文件hash可以用于去重、秒传和完整性校验。
收藏功能可以覆盖文本、图片、文件、语音、链接、名片等内容。收藏时建议保存内容快照,而不是只保存原消息ID。因为原消息可能被撤回、删除或清理,保存快照可以保证收藏内容的可用性。
13. 朋友圈模块设计
朋友圈属于基于好友关系链的内容模块。常见功能包括发布图文动态、点赞、评论、删除动态、动态详情、好友动态流和可见范围设置。
朋友圈的数据可以拆成动态主表、图片表、点赞表、评论表和可见范围表。动态列表查询时,需要结合好友关系、屏蔽关系和动态权限进行过滤。
可见范围通常包括:
- 公开
- 仅好友可见
- 部分好友可见
- 不给谁看
为了提高列表性能,可以在动态主表中冗余点赞数、评论数、图片数量等字段。详情页再加载完整评论和点赞列表。
14. 语音通话、视频通话与多人语音会议
语音通话和视频通话一般由信令服务和媒体服务共同完成。IM系统主要负责信令部分,例如发起通话、接受通话、拒绝通话、取消呼叫、挂断、忙线、超时等事件。
多人语音会议不同于普通一对一通话。它需要会议房间、成员状态、静音状态、主持人控制、加入退出通知等能力。群聊中发起多人语音会议时,可以先创建会议房间,再向群成员发送会议邀请消息。成员加入后,服务端维护会议成员状态,并同步给其他参会用户。
15. i18n多语言包设计
i18n多语言包适合需要多地区使用的IM系统。前端可以将菜单、按钮、提示语、错误信息、消息状态统一抽离成语言Key。
例如:
{
"chat.send": "发送",
"chat.revoke": "撤回",
"group.mute": "禁言",
"wallet.balance": "余额",
"message.read": "已读",
"message.unread": "未读"
}
后端接口也可以根据请求头中的语言参数返回不同语言的错误提示。这样后续增加语言时,不需要大量修改业务代码。
16. 部署、集群与扩展设计
部署方式可以根据业务规模分为单机部署和集群部署。
开发或测试环境中,后端服务、IM服务、MySQL和Redis可以部署在同一台机器上,便于调试和一键启动。
正式环境中,可以将系统拆成多个服务:
- IM连接服务
- 业务API服务
- 文件服务
- MySQL数据库
- Redis缓存
- 静态资源服务
- PC端前端服务
- H5前端服务
集群部署时,IM连接节点可以横向扩展。用户连接到不同节点后,需要通过Redis或统一路由服务维护用户在线状态和连接位置。消息投递时,如果接收方连接在其他节点,需要通过节点间通信完成跨节点投递。
SSL/TLS加密传输可以用于HTTP、WebSocket和Socket协议,保护登录、聊天、红包、钱包和文件传输过程中的数据安全。
17. API接口与二次开发边界
一个完整的IM系统通常需要提供以下接口模块:
| 接口模块 | 主要内容 |
| 用户接口 | 登录、注册、用户资料、头像、昵称 |
| 好友接口 | 好友申请、好友列表、删除好友、拉黑 |
| 群接口 | 创建群、群成员、群公告、禁言、入群审核 |
| 消息接口 | 历史消息、离线消息、撤回、已读未读 |
| 钱包接口 | 余额、流水、充值、提现 |
| 红包接口 | 发红包、领红包、红包记录 |
| 文件接口 | 上传、下载、文件消息 |
| 朋友圈接口 | 发布动态、点赞、评论、动态流 |
| 收藏接口 | 收藏消息、收藏文件、收藏图片 |
| i18n接口 | 语言包、语言切换 |
如果项目代码需要支持可商用、二次开发和独立部署,研发团队应重点关注代码结构、数据库表结构、接口文档、协议文档、部署文档和配置说明。只有前端、后端、数据库、缓存、协议和部署链路都具备清晰边界,后续业务扩展才会更可控。

18. 技术落地时需要重点关注的工程问题
在实际研发即时通讯APP时,前期可以先完成账号体系、好友关系、单聊、群聊、消息持久化、离线消息和多端同步。红包、钱包、朋友圈、音视频通话、多人语音会议等模块可以在基础通信链路稳定后逐步接入,避免一开始把所有业务耦合在同一套消息逻辑中。
18.1 消息表与会话表需要提前规划
消息数据量增长速度通常很快,单聊、群聊、文件、图片、语音、红包、名片等都可能进入消息体系。设计数据库时,可以将会话表、消息主表、消息扩展表、用户会话表分开处理。
会话表主要记录会话ID、会话类型、最后一条消息、最后更新时间等信息。消息表主要记录消息ID、发送人、接收对象、消息类型、消息内容、服务端序号、发送时间等信息。用户会话表可以记录每个用户的未读数、置顶状态、免打扰状态、草稿内容和最后已读位置。
这样设计后,聊天列表查询、历史消息分页、未读数统计、多端同步都会更清晰。
18.2 Redis缓存需要控制边界
Redis适合保存在线状态、连接路由、群成员缓存、未读数、红包领取锁、验证码、临时Token等高频数据,但不适合替代MySQL作为最终数据源。
例如用户在线状态可以存储为:
im:online:user:{userId} -> nodeId、connectionId、deviceId、lastActiveTime
群成员缓存可以存储为:
im:group:members:{groupId} -> userId list
未读数可以存储为:
im:unread:{userId}:{conversationId} -> unreadCount
缓存设计需要考虑过期时间、缓存更新、缓存击穿和数据回源。群成员变更、用户退出登录、消息已读、红包领取等操作,都需要同步处理缓存状态。
18.3 群聊扩散策略需要根据规模调整
小群和大群不适合使用完全相同的消息扩散方式。几十人以内的小群,可以采用写扩散方式,在消息发送时为每个群成员生成收件记录,查询未读和历史消息都比较直接。
如果群规模较大,写扩散会带来明显写入压力。此时可以考虑读扩散或混合扩散模式。群消息只写一份,用户读取时根据加入群时间、最后已读位置和消息序号进行拉取。对于活跃成员,可以结合缓存维护未读状态,减少频繁扫描数据库。
18.4 多端同步要独立成事件机制
四端支持意味着同一个账号可能同时登录安卓、iOS、H5和PC端。用户在任意端发送消息、撤回消息、阅读消息、收藏消息、删除会话,都需要同步到其他在线设备。
这类能力不建议写散在各个业务接口中,可以统一设计为设备同步事件,例如:
{
"cmd": "sync",
"event": "conversation_read",
"userId": "10001",
"conversationId": "single_10001_10002",
"readSeq": 1088,
"syncTime": 1781517600000
}
服务端在处理状态变化后,将同步事件推送给同账号下其他在线设备。这样可以保持手机端、H5端和PC端的会话状态一致。
18.5 钱包和红包需要独立事务链路
红包和钱包不要直接混在普通消息发送逻辑中。红包消息可以作为聊天消息展示,但红包创建、余额扣减、领取记录、钱包流水必须走独立事务链路。
发红包时,先完成余额校验和红包记录创建,再发送红包消息。领红包时,先判断红包状态、剩余金额、剩余数量、用户是否已领取,再写入领取记录和钱包流水。聊天消息只负责展示红包卡片,不负责决定资金状态。
18.6 文件消息需要考虑权限和生命周期
文件发送并不是简单上传一个URL。文件消息需要记录文件名、文件大小、文件类型、文件hash、上传用户、所属会话、上传时间和访问权限。
如果用户退出群聊,是否还能下载历史文件;如果消息被撤回,文件是否继续保留;如果文件被收藏,原文件过期后收藏是否还能访问,这些都需要在文件生命周期中提前定义。
18.7 i18n多语言不只处理前端文本
i18n多语言包除了前端按钮、菜单、提示语之外,还需要考虑后端错误提示、系统通知、消息状态文案和钱包流水类型文案。
例如“红包已领取”“消息已撤回”“群主已开启全员禁言”“文件不存在或已过期”等提示,如果只写死在后端或前端,后续增加语言会增加维护成本。更合理的方式是前后端使用统一语言Key,再根据用户语言环境渲染对应内容。
18.8 部署配置需要区分开发、测试和正式环境
即时通讯系统通常涉及HTTP服务、WebSocket服务、Socket服务、MySQL、Redis、文件服务、PC端静态资源、H5端静态资源等多个部分。即使支持一键启动,也需要把配置项拆清楚。
常见配置包括:
- 数据库连接
- Redis连接
- IM服务端口
- WebSocket地址
- Socket端口
- 文件上传路径
- SSL/TLS证书
- 日志路径
- 消息存储策略
- 离线消息保留时间
- 钱包交易开关
- 多语言默认配置
配置结构清晰后,后续从单机部署切换到集群部署会更容易,也方便研发团队排查线上问题。
更多推荐



所有评论(0)