即时消息技术剖析与实战
袁武林
微博研发中心技术专家
立即订阅
6503 人已学习
课程目录
已完结 24 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 搞懂“实时交互”的IM技术,将会有什么新机遇?
免费
基础篇 (8讲)
01 | 架构与特性:一个完整的IM系统是怎样的?
02 | 消息收发架构:为你的App,加上实时通信功能
03 | 轮询与长连接:如何解决消息的实时到达问题?
04 | ACK机制:如何保证消息的可靠投递?
05 | 消息序号生成器:如何保证你的消息不会乱序?
06 | HttpDNS和TLS:你的消息聊天真的安全吗?
07 | 分布式锁和原子性:你看到的未读消息提醒是真的吗?
08 | 智能心跳机制:解决网络的不确定性
场景篇 (4讲)
09 | 分布式一致性:让你的消息支持多终端漫游
10 | 自动智能扩缩容:直播互动场景中峰值流量的应对
11 | 期中实战:动手写一个简易版的IM系统
12 | 服务高可用:保证核心链路稳定性的流控和熔断机制
进阶篇 (10讲)
13 | HTTP Tunnel:复杂网络下消息通道高可用设计的思考
14 | 分片上传:如何让你的图片、音视频消息发送得更快?
15 | CDN加速:如何让你的图片、视频、语音消息浏览播放不卡?
16 | APNs:聊一聊第三方系统级消息通道的事
17 | Cache:多级缓存架构在消息系统中的应用
18 | Docker容器化:说一说IM系统中模块水平扩展的实现
19 | 端到端Trace:消息收发链路的监控体系搭建
20 | 存储和并发:万人群聊系统设计中的几个难点
21 | 期末实战:为你的简约版IM系统,加上功能
22 | 答疑解惑:不同即时消息场景下架构实现上的异同
结束语 (1讲)
结束语 | 真正的高贵,不是优于别人,而是优于过去的自己
即时消息技术剖析与实战
登录|注册

20 | 存储和并发:万人群聊系统设计中的几个难点

袁武林 2019-10-11
你好,我是袁武林。
我在场景篇的第 10 讲“自动智能扩缩容:直播互动场景中峰值流量的应对”中,分析了直播互动场景中,容易出现瓶颈的原因主要在于:“直播间人数多,短时间内活跃度高,消息的扇出量巨大”。
那么,对于同样属于多人互动的群聊场景来说,虽然在“群人数”等方面与高热度的直播间相比要少一些,但由于同时开播的直播间数量一般不会太多,所以群在数量上的总体量级相对要大得多,可能上百万个群同时会有消息收发的情况发生。因此,在整体的流量方面,群聊场景的消息扇出也是非常大的。
而且和直播互动场景不太一样的是,直播互动中,热度高的直播活动持续时间都比较短,可以借助上云,来进行短时间的扩容解决,成本方面也比较可控;但群聊的场景,一般是流量总量高,但是峰值没有那么明显,靠扩容解决不太现实。因此,更多地需要我们从架构和设计层面来优化。
今天,我们就一起从架构设计层面,来聊一聊万人群聊系统中的几个难点,以及相应的解决方案。

群聊消息怎么存储?

首先来看一看群聊消息存储的问题。
关于点对点聊天场景,我在第 2 课“消息收发架构:为你的 App,加上实时通信功能”中也有讲到:我们在一条消息发出后,会针对消息收发的双方,各自存储一条索引,便于双方进行查询、删除、撤回等操作。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《即时消息技术剖析与实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(15)

  • clip
    思考题:
    看情况考虑。
    不好的地方:
    所有网关机都要从消息队列消费这条数据,但最终只有一台机器处理,比较浪费处理资源。对这条消息而言本来可以直接下推,结果要多经过了网关机,实时性可能会受到大群的影响。
    好的地方:
    不过采用网关机方案可以省去维护中央的在线状态。
    决定:
    可以根据业务的特点权衡一下,如果主要的会话都发生在群聊,私聊极少且实时性要求低那可以采用网关机维护的方案,反之不采用。

    作者回复: 基本没错,不过这里有一点说一下:不管是不是网关机维护本地状态的方式,消息最终下发都是需要通过网关机推下去的哈,只是网关机本地维护状态的方式会浪费掉一些其他网关机的计算。

    2019-10-11
    6
  • zhxh
    如果通过订阅的方式,那么这条消息应该也需要把群成员列表带给网关吧,否则网关怎么筛选,可是万人群成员比较多,会导致这个消息包比较大,如果不带成员列表信息到网关,那么要求用户在和网关建立连接的时候,就要把自己加入的群列表信息带过来,绑定到网关,这样逻辑似乎和网关耦合比较严重,老师能详细解释一下么

    作者回复: 不需要建连时耦合群信息相关内容,这个问题可以采用分批下发给网关来解决,比如一批100这样。

    2019-10-11
    2
    4
  • clip
    群聊的私有类型消息是不是要采用补齐而不是剔除的逻辑?因为加了一条仅自己可见的消息给其他人都创建不可见索引就得不偿失了。

    作者回复: 嗯,是的,私有消息是聚合,删除是剔除。

    2019-10-11
    2
    3
  • leslie
    其实点对点的在线下推:个人理解就是非常考验中间件存储/数据系统的设计,不合理的设计必然造成某块的负载过大,如何合理的设计和使用这些东西会成为关键。
       老师的图中就有MQ和RMDB其实还有Nosql DB:刚好今天李玥老师的MQ刚刚完课,看完了老师的21课反向来学习这课的;看过国内的一些IM,其实这块真实的设计都被隐藏了;个人觉得这块如何修正成为自己的东西如何利用和设计好中间件存储应当是IM设计的一块重点和难点。
        IM有听闻说简单的可是老师的课程学到现在:我发现如何合理的设计应用架构、数据系统、以及配合合适的监控应当是系统成败的关键。谢谢老师辛勤的分享以及困惑时的提点和教诲。

    作者回复: 哈哈,感谢支持和肯定~

    2019-10-15
    1
  • 黄海
    请袁老师看一下这样的方案行吗:把各台网关机上的在线群(在线群成员数>0)的群 uid 作为 key,把网关机的消息队列 topic 作为 value,写入 redis set 中,发送群消息时,根据 key 群 uid 从 redis set 中查出群成员分布在哪些网关机上,然后通过消息队列,精准的向这些网关机推送群聊消息

    作者回复: 这个方案的问题在于:群聊的使用场景并不存在说“某个用户在某个群在线”这么个说法,和直播的房间概念是不一样的。可以认为只要用户上线就应该处理所有群的消息。

    2019-10-14
    3
    1
  • 墙角儿的花
    老师 用websocket做长链接通信在网络较好情况下没什么问题 但在弱网下如2g 3g下就会频繁掉线,但是微信却做的这么好,地铁里仍然很稳定,它走的绝对不是websocket,它怎么做到的这么稳定通畅呢?有什么资料可以查看学习吗。

    作者回复: 之前有提到微信手机端应该走的是tcp私有协议,不是websocket。另外你提到的websocket弱网下容易掉线这个得具体case分析一下,不能把这个归结到websocket协议本身,底层一样都是基于tcp来传输的。连接不稳定和很多因素有关,连接入口的是否够快,有没有故障转移通道,能否快速识别到连接断开然后快速进行重连,网络传输的数据是否够小够精简,这些都有关系。微信有一些公开对外演讲的资料,可以查一下。

    2019-10-11
    2
    1
  • 我行我素
    老师,想请问下:在用户删除消息的时候,把这条被删除消息加入到当前用户和群维度的一个删除索引中,这一步不是很明白

    作者回复: 其实就是把群聊消息删除这个单独记录一下,比如一个list里面,key是 uid_群id,value是这个uid在这个群删除的消息id。最后这个用户获取群消息时,从群维度的全量消息里剔除掉这个用户在这个群删除的这些消息id。

    2019-10-11
    1
    1
  • 秋日阳光
    万人群聊,系统是维护了万个TCP链接吗?

    作者回复: 这里的意思是一个群有一万人的这种超大规模群。只有在线的用户才会建立长连

    2019-10-11
    2
    1
  • 🐾
    老师上午好、有些疑惑想跟您确认一下,消息多终端漫游,为解决用户离线期间收不到消息的问题,我们会在服务端按照接收用户维度,暂存用户离线期间的消息,等该用户下次上线时再进行拉取同步。
    1、这里的同步,实际上是把服务端的消息同步到客户端,客户端也保存这些消息吧?
    2、假如用户重新安装了APP,把客户端保存的数据也清空了,像这种情况下,一般处理是只同步离线消息,不同步历史数据吗?
    3、如果客户端不保存消息记录,但又要显示所有历史数据,是不是不需要设计这个离线存储了,直接读取会话维度的所有消息就好?

    作者回复: 1. 是的。
    2. 一般这种情况可以只下推离线消息,历史消息通过用户来触发拉取。
    3. 不保存消息记录是指客户端不在本地存储所有消息?这种方式不太好呀,要不没网就看不了所有聊天记录了。

    2019-10-11
    1
  • 墙角儿的花
    群聊信息如果不采用收发箱的方式存储,碰见钉钉这种需要记录查看一条群消息哪些成员已阅,哪些未阅,就无能为力了

    作者回复: 这个是个问题,实际上也可以不需要按照uid维度来存储消息,按照消息维度存储已上报过 阅读事件的uid就可以。

    2019-10-11
    2
    1
  • 三达不溜
    老师,关于“网关机自治维护本地在线状态”有个问题想请教下,就是如果点对点或者群聊使用这种方式消息进行的话,系统如何全局感知到需要发送的用户此时不在线,进而使用apns进行推送呢
    2019-12-08
  • null
    老师,如果用户将群消息全删除,是存全部的消息索引到消息删除表么了?如果这样的话,当存在较多用户删除群消息时,消息删除表,就成了用户维度的群消息存储表了。

    作者回复: 理论上出现极端情况是会的,但在我们的实践里很少出现大量用户删除某个群的群消息的情况。

    2019-11-28
  • yic
    老师,看了这么多节课程,突然有个问题想问:像微博、微信等这些APP一般的实时在线人数大概是什么量级?一台网关机大概能承载多少在线用户呀?

    作者回复: 像微博是千万级在线,微信具体数据不太清楚。单台网关机虽然理论上能到百万级别,但线上一般控制在几十万比较正常,如果是类似直播的业务会控制在更低水平。

    2019-11-21
  • 独酌相思解千愁
    思考题:个人觉得对于点对点消息下推不适合采用网关自治维护本地在线状态。原因是本来采用中央维护的模式点对点只需要涉及个别网关机就能完成下推,采用自治维护后由于在线状态对于其他网关机是不可见的,在消息下推时就要采用类似广播的方式,将消息下推给每个网关机,这些网关机再再自己的维护的在线状态表中找这个目标用户,如果有就下推给他,如果没有就结束(自己意想的过程)。这个过程中会会浪费很对网关机的资源,且做了太多无用工。另外想问下,真实场景比如说QQ,微博这些是两种模式结合的么,点对点就查询中央,若识别出来是群聊就优先查网关自治的么?

    作者回复: 没问题的,非扇出类型的场景可以直接通过在线状态来精确下发,减少网关机负载。

    2019-11-12
  • 天天向善
    末读变更服务下的buffer queue是中间件吗,timer,flusher也是单独应用?没有明白,能不能再详细介绍下

    作者回复: 整个这个buffer组件是一个in jvm的组件,timer和flusher是两个功能实现类。可以参考我们前同事开源出去的一个实现:github搜bufferslayer。

    2019-10-17
收起评论
15
返回
顶部