即时消息技术剖析与实战
袁武林
微博研发中心技术专家
24187 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 25 讲
即时消息技术剖析与实战
15
15
1.0x
00:00/00:00
登录|注册

02 | 消息收发架构:为你的App,加上实时通信功能

思考题
小结
消息未读数
消息收发通道
消息存储
消息收发架构

该思维导图由 AI 生成,仅供参考

你好,我是袁武林。
前一篇文章中,我们从使用者的直观角度和从业者的实现维度,了解一个 IM 系统都应该具备哪些要素。但实际上,从我的角度来看,我更倾向于把“IM”看作是一门可以融入到各种业务系统中,为业务系统提供“实时交互”能力的技术模块。
比如,极客时间想在它的 App 中增加一个互动模块,支持用户点对点的实时聊天功能。那么,我们就可以相应地通过一些 IM SDK 的方式,快速地把即时消息的技术引入到已有的业务系统中。
同样,一个传统的视频网站如果想让自己的视频支持弹幕功能,也可以通过引入即时消息的技术,来让视频弹幕的参与者能实时、高效地和其他观看者进行各种互动。
所以,从某种程度上看,随着移动网络的快速发展以及资费的快速下降,即时消息技术也越来越多地被广泛应用到各种业务系统中,用于提升用户实时互动的能力。
那么,接下来,我们就一起从即时消息更细化的实现角度来看一看,给一个已有系统增加即时消息功能,大致上都有哪些具体工作。
如果为原有的业务系统增加实时消息模块,在不需要重建账号体系的前提下,整体上大概包括几块内容:
一般来说首先需要制定好消息内容和未读数的存储,另外需要建立比原业务系统更加高效实时的消息收发通道,当然也包括依托第三方辅助通道来提升消息到达率。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

消息收发架构是实现实时通信功能的关键技术模块,为各种业务系统提供实时交互能力。随着移动网络的快速发展和资费的下降,即时消息技术被广泛应用于各种业务系统中,以提升用户实时互动的能力。在为原有业务系统增加实时消息模块时,需要制定消息内容和未读数的存储方式,并建立高效实时的消息收发通道。消息存储方面,需要设计消息索引和消息内容表,以及联系人列表,用于存储历史消息和最近联系人信息。消息收发通道方面,可以通过IM服务端提供的HTTP协议的API接口或维护TCP长连接来实现消息的发送和接收。整体上,为业务系统增加实时消息功能需要考虑消息存储和消息收发通道两个方面的具体工作。 消息接收通道是实现非P2P模式的IM系统的关键组成部分。通过维护TCP长连接,IM服务端能够实时将消息推送给接收方,同时利用第三方手机操作系统级别的辅助通道,如APNs和GCM通道,来提升消息的实时触达能力。对于消息未读数,它是一个重要的补救措施,可以帮助用户及时感知到新消息的到来。在实现上,需要针对用户维度和会话维度分别进行未读数的计数,并通过IM服务端或本地端进行存储。整体上,消息的发送、存储、接收的生命周期较为完整,但未读数提醒对于用户互动积极性和频率有重要影响。 综上所述,本文从消息系统的实现角度对消息的发送、存储、接收等关键部分进行了讲述。通过发送通道将消息提交到IM服务端,进行消息存储和未读数变更后,通过接收通道将消息实时推送给接收方。最后,留给读者两个思考题,引发进一步讨论。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《即时消息技术剖析与实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(77)

  • 最新
  • 精选
  • 王棕生
    1. 消息存储中,内容表和索引表如果需要分库处理,应该按什么字段来哈希? 索引表可以和内容表合并成一个表吗? 答: 内容表应该按主键消息ID来哈希做分库分表处理,这样便于定位某一条具体的消息;索引表应该按索引的用户UID来哈希做分库分表处理,这样可以使得当前用户的所有联系人都落在一张表上,减少遍历所有表的麻烦。 索引表可以与内容表合成一张表,好处是显而易见的,能减少拉取历史消息时的数据库IO,不好的地方就是消息内容冗余存储,浪费了空间。 2. 能从索引表里获取到最近联系人所需要的信息,为什么还需要单独的联系人表呢? 答: 如果从索引表中获取一个用户的所有联系人信息(包括最后一条聊天内容和时间)的话,SQL语句中会有分组后取top 1的操作,性能不理想; 另外当前用户与单个联系人之间的未读数需要维护,用联系人表的一个字段来存储,比用索引表方便许多。

    作者回复: 👍

    2019-08-30
    6
    112
  • hlai
    最后张图,客户端发消息到服务是通过API, 请问为什么不可以长连接么发过去呢?

    作者回复: 这里说一下:消息的收发是可以通过同一个长连通道来实现的,对于普通的聊天场景我甚至更推荐这种架构。对于消息下行扇出压力较大的场景(比如:直播、大型聊天室),考虑到下行通道的压力较大,稳定性方面保障会差一些。这种情况可以将上行独立拆分出来,保证用户发消息不会受到消息下推压力大的影响。

    2019-11-29
    22
  • 666
    想了解一下像微博这类消息系统如果解决大V用户的消息收发的?比如用户给大v点赞、评论或者是私信

    作者回复: 点赞、评论这些目前采用的拉取模式,用户打开具体的赞箱和评论箱时才从服务端获取;私信是支持在线推送的,不过为了减少对大V的骚扰,对于未关注人私信没有系统push。

    2019-09-13
    6
  • 关汉聪
    老师,您的一个回复中写到:“一般会先写缓存层,缓存层都成功的情况下,如果写有索引失败的情况可以先把失败的索引先写入到一个“失败队列”,由其他线程轮询尝试来写入。一般情况下,缓存层可以抗住db重试期间的数据可用性。” 想问下,缓存一般都是缓解读压力用的,这里是为了缓解写压力,那么: 1. 缓存服务器也是要主从或者集群吗,这样每次写入都保证主从缓存都写入后,在写入DB之前,返回消息发送方,成功的ACK,对吗? 2. 如果缓存成功,索引写入DB失败,在“失败队列”被轮询的过程中,消息发送方接下来的每一条消息,为了保证消息的顺序,是不是都要等待之前失败的消息写入DB后,接下来才能发送给消息接收方? 谢谢老师。

    作者回复: 1. 缓存在这里的作用主要是快速响应用户的写入请求,规避同步写db的重操作。缓存服务器是否需要采取主从集群可以根据实际访问量来评估,一般写完主后即可返回,由主负责同步消息到从。 2. 由于消息id和产生时间在写入缓存前就已经生成好,失败队列重试导致的顺序错乱不影响最终消息到达客户端后的重排序。

    2019-12-18
    2
    5
  • Dxn
    索引表为啥要插入两条记录?插入一条也是一样的啊

    作者回复: 主要是考虑各自索引维护时的独立性:比如一方删除了消息不影响另一方查看类似的需求。

    2019-11-03
    3
    4
  • 小祺
    消息表和索引表合并后表结构: 发消息用户ID ,收消息用户ID, 消息状态, 消息内容,消息类型,消息产生时间 其中消息状态 0: 正常 1:发消息用户已删除 2: 收消息用户已删除 如果两个用户都删除消息,那这条记录就被delete掉。 既可以满足合并消息,又可以满足单个用户删除消息,请问这样设计是否可行?

    作者回复: 处理删除和合并上没问题哈,需要考虑一下分库分表场景下,收发双方查询历史消息应该怎么查呢?

    2019-09-03
    6
    4
  • Alber
    消息存储有什么推荐的数据库吗

    作者回复: 这个需要看具体的业务场景吧,比如考虑访问模型,数据量大小,读写的比例等等。在我们自己的场景里mysql和hbase,pika都有在使用。

    2019-08-30
    4
  • 小袁
    索引表按照聊天对像的id来哈希,这样和某个对象的聊天记录可以落在一个库中,没问题。 内容表我认为可以按时间分库,实际查询时一般都是从最近的聊天记录开始往前翻,或者看某一天的记录,这样按连续时间段来查询,不会只单独看一条记录吧。 如果按消息id分库那岂不是翻某天的聊天记录可能要查好几个库了吗?

    作者回复: 按时间段来查询没问题,但是消息写入的时候就会都落到一个表里,写入压力会有问题,但内容表实现上确实可以在hash完后按时间进行分表。

    2019-09-07
    2
  • geraltlaush
    之间面试被问到怎么设计存储群聊的聊天记录,保证聊天记录的有序性,没答出来,老师帮忙解答下

    作者回复: 一般来说群聊消息的存储上主要是考虑存储冗余的问题,一个群的消息只需要存一份即可,每条消息id通过自增序号或者“时间维度相关”的发号器来生成,通过这个id排序即可。群聊相关的话题后续课程还会细讲哈

    2019-09-02
    2
  • 挨踢菜鸟
    老师,请问websocket如何多实例部署,如何解决实例重启造成连接断开的问题

    作者回复: 没太理解到您的意思哈,websocket网关只有是无状态的多实例部署没啥问题的呀;实例重启断开连接是肯定的,需要解决的是断开后客户端需要有重连机制以及如果尽量减少实例重启的概率。

    2019-08-30
    9
    2
收起评论
显示
设置
留言
77
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部