如何设计一个IM单聊架构

IM-后台搭建(二)之数据库设计 这一篇主要讲解我们后台数据库表的设计。 可以看到我们的数据库表一共有七个,每个表都以TB开头,其实对于一个IM软件,七个表只能勉强实现其功能,还是有很多表需要扩展的。我们来介绍一下七个表分别的作用。 TB_USER:从上面图中也可以看出,这个表示最核心的表了。与其他六个表都有关联。用来存储用户的信息。 TB_GROUP:用来存储群组的信息。 TB_GROUP_MEMBER:用来存储群成员相关的信... 阅读详情

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:juejin.cn/post/

7110536715764236296

bdad8d234b25f8efef929e46f6a26560.jpeg


单聊

在众多的软件中,聊天功能是不可或缺的一个功能模块,或是用户和用户,或是用户和客服,都需要一个能够即时沟通的功能。

那么一个IM(InstantMessaging)的1对1聊天系统架构和存储应该如何设计呢。

下面来一步步的分析规划。

一. 功能点拆分

首先来看一个IM软件模块包括哪些基本功能

  • 会话列表(需要按照最后一条消息时间的倒序,将会话进行排列)

  • 聊天内容页(单聊双方的消息按时间顺序依次排列)

  • 未读消息计数(发送了但是没有读取的对话,需要在头像旁显示未读数字)

  • 用户头像,昵称(对话的用户资料)

根据上述功能点拆分后,可以确定下来需要哪些数据存储

  • 会话列表

  • 聊天的消息记录

  • 离线消息列表

  • 未读消息数据数量

  • 用户资料

二. 数据结构

实际进行下面几种数据结构存储时,可使用适合自己的场景的组件,例如公司自研的,或熟悉并满足场景要求的。

以下我拿redis或mysql来举例子,提供一个思路,实际生产环境还需要具体设计和选型

1. 会话列表

首先,需要为每一个会话创建一个会话Id进行标识。

再来看,会话列表的特性是新来消息的会话需要排在列表的上面,那么就可以使用一个有序集合SortedSet来存储。

结构如下:

key: prefix_xxx:{uid} value: {会话Id} score: {msgId}

key使用当前用户的uid来标识,集合中的每个item则是会话的Id,item的score为会话的最后一条消息的Id,这样根据score自动形成一个有序集合后,就能够满足我们的应用场景了。

2. 单聊消息列表

场景:聊天的消息列表,是一个按照时间顺序来排列的消息记录,并且需要可以根据offset来进行数据拉取。

同样可以使用redis的有序集合SortedSet来存储会话的消息列表,通过scan拉取消息

key: prefix_session_list:{sessionId} value: {msgId} score: {msgId}

也可以创建一个Mysql数据表来持久化存储消息记录

create table t_msg_record_list (
`id` bigint not null primary key,
`sessionId` bigint not null comment '会话Id',
`msgId` bigint not null comment '消息Id',
`isRead` tinyint not null default 0 commment '已读状态',
`recordStatus` smallint not null default 0 commment '消息状态',
`createTime` datetime not null,
key `sessionId` (`sessionId`) 
)engine=innodb;

根据会话Id分页查询时,就可以这样查询出所有msgId,再根据msgId去拉取msg的详情,组合成列表返回给客户端

SELECT msgId FROM t_msg_record_list WHERE sessionId = 1 AND recordStatus = 0 AND msgId > 1 ORDER BY id desc LIMIT 10;
3. 离线消息

离线消息可以分为「索引」和「消息id列表」两部分

离线消息索引需要记录的是,哪些用户给当前用户发送了离线消息,所以我们可以使用redis的集合Set来记录这些信息

key: prefix_xxx:{uid} value: {senderUid}

通过scan离线消息索引拿到了sendUid,再去拿这个会话的具体的离线消息id列表

然后,消息id列表使用redis的一个list链表来存储

key:prefix_offline_msg:{uid}:{senderUid} value:{msgId}

拿到所有msgId以后,去获取msg的实体详情填充即可

4. 未读计数

未读计数= 收到消息总数 - 已读数量

所以我们要存储两个已知数据便于计算出未读数量,即消息总数量和已读数量

由于对话存在双方发消息,所以分别维护对话双方的两个数据项,方便计算各自的未读数

接受消息总数量

key: prefix_session_count:{会话Id}:{uid} value: 总数量

已读数量

key: prefix_session_read_count:{会话Id}:{uid} value: 已读数量

5. 用户资料

使用mysql按需设计即可,变更保存后将数据同步到redis中使用

三. 架构层级拆分

52d6f9c92e8baf3e24b067b7140092d9.png

如图所示,我们可以将架构大致分为五层,具体说明如下

1. 客户端层

我们IM服务的client肯定是有多个,web/app等,需要封装多种SDK隐藏底层细节,便于接入方接入。

2. 连接层

即时通讯需要客户端和服务端之间建立一个长链接,一方面维护用户的在线状态,另一方面便于复用连接进行消息的收发。

而维护连接这个动作,它的独立性很强,不需要与业务逻辑耦合,所以我们把链接层单独拆分出来一个。

这样在业务逻辑迭代上线时,业务层进行滚动上线也不会导致用户的链接断开。

连接协议

至于连接协议的选择,有如下几种方式

  1. 基于tcp链接,自定义传输协议(开发成本高,需要有一定条件)

  2. websocket

  3. http chunk (不建议使用,http工作在7层上,且只能服务端单向的向客户端传输数据,心跳连接不好维护)

这里推荐优先使用四层的协议来进行长链接的维护。

因为长链接集群的前方要做负载均衡,使用七层的协议,客户端要先和负载均衡机器建立链接,然后负载均衡机器再和业务层集群交互。

这样在连接数很大的时候,负载均衡的机器容易成为瓶颈。四层的负载均衡可以直接通过修改目标机器ip prot的方式来进行转发,不需要client和负载均衡机器建链接

3. 业务层

业务层可以分为「长链接业务层 」和「短链接业务层 」

具体两者的功能拆分,可根据业务实际情况设计

  • 长链接业务层: 负责会话相关的业务逻辑,比如收发消息/拉取会话列表/未读计数push等业务

  • 短链接业务层: 负责一些临时接口请求,比如用户资料拉取/资料变更等类似业务

两种业务层都通过调用服务层来进行数据读取和写入等擦欧总

4. 服务层

这层属于微服务,来为上层业务层提供基础服务能力,例如敏感消息过滤/会话列表数据读写/消息的落地和发送等功能。

5. 数据层

为上层的服务层来提供数据的实际落地写入,可以使用mysql,redis或其他sql/nosql数据库。

四. 推拉模式选择

那么在消息的发送上,我们应该选用推模式,还是拉模式,抑或是推拉结合呢?

1. 纯推模式

首先,我们假设使用纯推模式 ,来看会存在什么样的问题

场景1: 新设备登陆初始化

用户新登陆一台设备的时候,如果消息记录全都是空的,体验会很不好。

那么就需要服务端推送全量 的消息记录到客户端,历史消息量大的时候,非常浪费服务端资源和带宽。

场景2: 设备间切换
92d6f11cfde5808f998c019c6544f4bc.png

tips:设备A和B都非第一次登陆

如图所示,流程如下

  1. 用户1在设备A上登陆,收到了用户2的消息1和2,push到了设备A上。

  2. 用户1退出了设备A,用户2又给他发送了消息3和4

  3. 用户1登陆了设备B,服务端push消息3和4到了设备B

但是此时,设备B缺少了消息1和2,用户再登陆回设备A的话又缺少了消息3和4,这也就产生了「消息空洞 」

2. 纯拉模式

然后,我们假设使用纯拉模式 ,来看会存在哪些问题

场景1: 收新消息

纯拉模式下,客户端需要和服务端进行一个长轮询,来定时检查是否存在新消息,并进行消息拉取。

这样轮询的时间间隔需要很难确定合适,间隔大了消息不实时,间隔小了无疑对服务器会产生很大的压力,无法支撑大量的在线用户进行聊天。

总结

由于推拉模式分别适用于业务中的不同场景需要,所以我们要使用推拉结合的方式来做。

拉模式适合的场景如下:

  1. 设备初始化时:先拉取会话列表,在根据会话的列表来为每个会话拉取一定的消息记录。可以通过控制拉取的数据量,减轻服务端压力。

  2. 历史聊天记录:按需拉取一定条数的记录,用户向上翻取记录再拉取固定条数的记录,直到翻到没有记录(就是翻页)。

推模式适合的场景如下:

  1. 用户实时接收消息

  2. 用户在线,有未读消息做通知栏push时

五. 消息流转

上面确定好推拉模式后,我们来看发消息和收消息都有哪些业务逻辑执行。

发消息
e2b307aff7a624061f77f881cdff7c74.png

如上图所示,大致可分为三步

1. 消息过滤

首先用户的消息通过客户端的SDK发送出来,通过长链接到达了「逻辑层」,逻辑层接收到该请求后,可以根据定义的拦截过滤规则调用「服务层」的服务接口,来对消息进行处理;

2. 消息补充

处理通过后,来对消息的发送方资料进行填充,简单来说就是senderId标识,接收方接收消息时能够填充到对应的会话中。

3. 派发任务

消息实体处理完成后,将该消息push到「服务层」的「异步任务队列」服务中。

异步队列任务 主要需要做以下四个方面的操作

  1. 更新存储端的「聊天记录」

  2. 更新会话的「消息总数量」,用来计算未读计数

  3. 根据接收方的在线状态来判断,是直接进行push,还是存入到离线列表中,等待用户上线后再进行消息拉取

  4. 更新「会话列表」的score值

具体异步队列还可以细化拆分,例如

  1. 实时任务队列

  2. 延时任务队列

  3. 失败重试队列 分别启动不同的线程池来消费任务,按需分配线程数处理

收消息

收消息主要有以下几个场景需要处理

  1. 客户端需要将消息append到聊天列表中,并在会话列表中将该会话增加未读消息标识。

  2. 如果接收方打开了开聊天窗口,客户端会发送一个消息的ACK给服务端,来标记该消息已读。

  3. 服务端收到已读ACK后需要更新「已读计数」相关数据项

  4. 如果是拉取离线消息,服务端还需要更新「离线消息」相关数据项

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

小结

本文从五个方面来对单聊的IM架构进行了设计分析

  1. 业务功能拆分

  2. 数据结构设计

  3. 系统结构设计

  4. 推拉模式选择

  5. 消息流转分析 讲了基础的结构有哪些,数据结构有哪些要求,以及消息流传的过程是什么样的。

对im单聊场景的开发框架有了大体的一个认识,但是实际落地的时候还有很多细节需要去实现。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

b11342b6aac1e13577ef132be4a0a6f8.png

已在知识星球更新源码解析如下:

16301b4d063f567db8ac2f0452c6347b.jpeg

f3a24b2b95096fc8bca61d809dfa66cd.jpeg

4c113432aa9b0cee46994c69bad9ff47.jpeg

cbed752c622c46d0ac561f57c2bc572f.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
IM 架构设计 在spring cloud 的基础上设计IM架构使用tcp长连接。 阅读详情

相关推荐

GPU资源池化:技术原理与应用场景全解析

GPU资源池化技术已成为AI时代高效利用算力的关键方案。该技术通过硬件虚拟化、容器化编排和智能调度三个核心层面,实现GPU资源的共享与优化,可将平均利用率从不足30%提升至60-80%。主流方案包括NVIDIA全栈解决方案、云原生Kubernetes生态及开源工具,适用于企业AI平台、大模型训练和边缘推理等场景。虽然面临性能隔离、资源碎片等挑战,但随着硬件虚拟化细化和AI驱动调度算法的发展,GPU池化正向着智能化、自动化方向演进,推动实现"算力如水电"的愿景。

技术引领业务创新 1352

搭建一个完整的 IM(即时消息)框架

即时消息(IM)应用在现代社会扮演着至关重要的角色,它们实现了快速、便捷的沟通和协作,无论是个人、企业还是社交关系。IM 应用加强了社交联系,提升了团队合作效率,也在教育、客户服务和危机应对方面发挥着重要作用。

特立独行的博客 2329

基于STM32与SimpleFOC实现直流无刷电机开环控制的实战指南

本文提供了一份基于STM32微控制器与SimpleFOC开源库实现直流无刷电机开环控制的详细实战指南。内容涵盖硬件连接、PlatformIO环境搭建、核心代码解析及上电测试,旨在帮助开发者快速验证硬件并理解开环控制的基本原理,为后续实现高性能的闭环FOC控制奠定基础。

xxx12的博客 960

IM 通讯整体架构与核心技术点概述

IM 通讯整体架构与核心技术点概述

nandao158的博客 4575

RK3568+XS9922B+Android11双模视频输入:CVBS与AHD兼容驱动开发实战

本文详细介绍了基于RK3568平台和XS9922B解码芯片,在Android11系统上开发支持CVBS与AHD双模视频输入的兼容驱动实战。内容涵盖硬件选型、内核驱动框架分析、双模信号自动识别与配置、视频通道切换实现及图像质量优化等关键技术点,为车载监控等需要兼容新旧摄像头的项目提供完整解决方案。

js777的博客 379

similarity network fusion for aggregating data types on a genomic scale

基因组规模上的聚合数据类型的相似性网络融合 摘要:         近期的技术已经使收集不同类型的全基因组数据十分划算,结合这些数据去创建一个给定的疾病或生物过程的一个全面视图的计算方法是有必要的。相似网络融合(SNF:similarity network fusion)通过创建每一个可利用的数据类型的样本(如,患者)的网络可以解决这个问题。例如,创建一个给定一群患者疾病的全面视图,SNF计算

augustar学习笔记 7869

架构系列---一套高并发IM通信系统完整设计和实现

先行参考:架构秘境系列3---微信、陌陌、WNS著名IM软件设计架构详解 1. 服务器端设计 1.1 总体架构 总体架构包括5个层级,具体内容如下图。 1.1.1 用户端 移动端重点是移动端,支持IOS/Android系统,包括IM App,嵌入消息功能的瓜子App,未来还可能接入客服系统。 1.1.2 用户端API 针对TCP协议,提供IOS/Android开发...

FeelTouch Labs 5400

微信架构设计:亿级IM聊天系统架构设计与重难点分析

IM系统就是即时通讯(Instant Messaging)系统的简称。IM其实并不局限于聊天、社交这类“典型”应用中,实际上它已经广泛运用于我们身边形形色色的软件中。聊天、直播、在线客服、物联网等所有需要实时互动、高实时性的场景等,都需要应用IM技术。1)微信、qq、钉钉等主流IM应用:这是IM技术的典型应用场景;2)微博、知乎等社区应用:它们利用IM技术实现了用户私信等点对点聊天;3)抖音、快手等直播/短视频应用:它们利用IM技术实现了与主播的实时互动;

秃了也弱了 7964

基于FLUENT的圆柱绕流数值模拟与流场优化策略

本文详细介绍了基于FLUENT的圆柱绕流数值模拟方法与流场优化策略。从基础概念、建模技巧到湍流模型选择,全面解析了圆柱绕流模拟的关键技术,并提供了实用的网格划分和参数设置建议。通过具体案例展示了流动控制方法和优化流程,帮助工程师有效降低阻力系数,提升流场性能。

f6g7h8i9j的博客 705

分布式光纤传感(DFOS)DTS/DAS/DSS 三合一:10公里管线监测实战与数据解读

本文详细介绍了分布式光纤传感(DFOS)技术在10公里管线监测中的实战应用,通过DTS(温度)、DAS(振动)、DSS(应变)三合一系统,实现对管线健康状态的立体感知。文章涵盖工程部署、数据采集、多物理量数据融合及噪声抑制等关键技术,展示了如何通过一根光纤完成复杂监测任务,显著提升管线安全性和维护效率。

weixin_29168153的博客 315

当IM遇上OpenAI,简历到底该怎么写?

为了能够让小伙伴们更好的理解分布式IM即时通讯系统的设计,我们站在架构师的角度,在充分了解系统需求,业务流程和技术流程后,从全局视角为系统设定方案目标,对技术方案进行选型,对系统进行总体架构设计和分层架构设计,并梳理清楚发送消息的交互链路、单聊和群聊的交互链路。以方便各位小伙伴将分布式IM即时通讯系统写到自己的简历中,增强自己的竞争力。

欢迎来到我的博客 918

【华为OD技术面试手撕真题】3、小行星碰撞 | 手撕真题+思路参考+代码解析(C & C++ & Java & Python & JS)

小行星碰撞,本专栏更新每年华为OD机试的高频手撕代码题,每个题目都会使用五种语言进行解答(C & C++& Java & Python & JS),思路分析都非常详细, 实现最低的时间复杂度和高通过率,每个解题思路超过百字,内含各个编程语言的八股文面试题,欢迎大家订阅学习, 代码可以直接运行使用,全网限时最低价,持续更新

KJ.JK 8170

【重磅开源】从零打造微信级IM系统!Vue3+SpringBoot双端实战

本文重磅开源了一套功能完整的IM系统——WebChat,采用Vue3+SpringBoot前后端分离架构,真实复刻微信核心体验。支持单聊群聊、语音录制、朋友圈、文件传输、实时消息推送等企业级特性,并深入剖析了WebSocket+STOMP、JWT+Redis互踢、MediaRecorder录音等高阶实现。

qq_45930467的博客 546

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Go项目推荐:分布式部署的仿微信项目KamaChat

摘要:KamaChat是一款基于Go语言开发的分布式仿微信即时通讯系统,包含1.5万行前后端分离代码,功能涵盖单聊/群聊、文件传输、音视频通话等核心功能。项目采用WebSocket和Kafka等技术实现实时通信,提供开发者管理、联系人体系等完整功能模块。开发耗时约200-300小时,支持自动化环境配置。项目配套详细技术文档、视频演示和面试指导,适合中高级开发者学习分布式系统开发经验。

代码随想录 473

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

深度解析 IM 单聊与群聊架构(一)

在当今互联网应用中,即时通讯(Instant Messaging,简称 IM)已经成为不可或缺的功能模块。无论是企业级应用(如企业微信、钉钉)、社交应用(如微信、QQ、WhatsApp)、游戏应用,还是垂直行业平台(在线教育、在线医疗、电商客服等),IM 的单聊与群聊功能都是核心交互方式之一。然而,IM 系统的架构设计并非简单的“消息收发”,而是涉及等一系列复杂问题。本博客将带你从深度理解 IM 单聊与群聊架构的全貌,从基础原理到架构演进,再到工程实践,形成完整的知识体系。

hsuhwsb的博客 1040

深度剖析 IM 单聊与群聊架构设计

协议字段设计:消息头(版本号、长度、类型、会话ID)+ 消息体(正文、扩展信息)。序列化方式:JSON(易调试)、Protobuf(高性能)、FlatBuffers(零拷贝)。选择策略:大规模 IM 系统一般选 Protobuf。IM 单聊与群聊系统的架构,从最初的点对点消息,到大规模分布式系统,经历了长时间的演进。整体架构概览单聊与群聊架构设计细节存储、可靠性与性能优化网络协议与弱网优化分布式与高可用架构安全与合规性未来趋势与演进方向。

hsuhwsb的博客 1042

从零到深度:IM单聊与群聊架构设计详解

本文系统介绍了即时通讯系统的架构设计,重点分析了单聊和群聊的技术实现。单聊架构主要涉及长连接维持、消息存储和可靠性保障;群聊则面临消息分发、成员管理和多端同步等复杂挑战。文章对比了写扩散和读扩散两种消息分发策略,并提出了混合方案。同时探讨了分布式架构设计、协议优化等关键技术,结合微信、Slack等实际案例,展示了IM系统从基础功能到复杂场景的演进路径。最后展望了未来与5G、AI等技术的融合方向。

hsuhwsb的博客 1385

IM 即时通讯系统-02-聊一聊 IM 要如何进行架构设计?

设计一个高效、稳定且可扩展的IM(Instant Messaging)消息系统需要从多个维度进行细致的架构规划。以下将从系统架构、数据库设计、网络通信、可扩展性、安全性、性能优化、维护与监控、用户体验、测试与部署以及文档与技术支持等方面详细阐述IM消息系统的架构设计。微服务架构将系统分解为多个独立的服务,每个服务专注于特定的功能模块(如用户管理、消息管理、实时通信等)。IM消息系统的核心功能是实时通信,因此选择合适的通信协议至关重要。客户端需要能够与服务器端建立稳定的连接,并且能够实时接收和发送消息。

2810

一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践

本文原题为“一套高可用群聊消息系统实现”,由作者“于雨氏”授权即时通讯网整理和发布,内容有些许改动,作者博客地址:alexstocks.github.io。应作者要求,如...

架构文摘 1668

环信IM快速集成集成,实现客服功能(单聊)

第一:你需要登入环信官网注册一个即时云通讯帐号和一个移动客服帐号。 创建一个自己的应用,获取APPkey等信息。 环信官网:http://www.easemob.com/ 第二:下载最新环信SDK,解压SDK后文件里包含HyphenateFullSDK,和HyphenateSDK  两个SDK  。前面的SDK里面包含了环信所有的功能,后面的SDK适合只需要一个简单的即时通讯功能。我

type雨过的博客 6317

分布式 IM 即时通讯系统的技术选型和架构设计

分布式 IM 即时通讯系统的技术选型和架构设计

安静的软件工程师 1649

聊一聊 IM 如何优化缓存

通过合理的优化策略,可以显著改善系统的运行效率,从而提升用户体验和系统整体表现。缓存优化是提升系统性能、响应速度和可扩展性的关键环节。

1619

聊一聊 IM 如何优化架构?

架构优化是提升系统性能、可扩展性、可靠性和可维护性的关键过程。它不仅涉及代码层面的优化,更涵盖了系统整体的设计和规划。

1030
上一篇: 你一看就是个水货...,这都不会!
下一篇: 因Redis分布式锁造成的S1级重大事故,整个团队都没年终奖了。。。
公众号-芋道源码
博客等级 码龄10年 1629粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值