20 | 存储和并发:万人群聊系统设计中的几个难点
20 | 存储和并发:万人群聊系统设计中的几个难点
讲述:袁武林
时长15:20大小14.04M
群聊消息怎么存储?
怎么保证新加入群的用户只看到新消息?
单个用户删除消息怎么办?
未读数合并变更
离线 Buffer 只存消息 ID
离线消息批量 ACK
不记录全局的在线状态
小结
赞 8
提建议
精选留言(26)
- clip2019-10-11思考题: 看情况考虑。 不好的地方: 所有网关机都要从消息队列消费这条数据,但最终只有一台机器处理,比较浪费处理资源。对这条消息而言本来可以直接下推,结果要多经过了网关机,实时性可能会受到大群的影响。 好的地方: 不过采用网关机方案可以省去维护中央的在线状态。 决定: 可以根据业务的特点权衡一下,如果主要的会话都发生在群聊,私聊极少且实时性要求低那可以采用网关机维护的方案,反之不采用。展开
作者回复: 基本没错,不过这里有一点说一下:不管是不是网关机维护本地状态的方式,消息最终下发都是需要通过网关机推下去的哈,只是网关机本地维护状态的方式会浪费掉一些其他网关机的计算。
10 - zhxh2019-10-11如果通过订阅的方式,那么这条消息应该也需要把群成员列表带给网关吧,否则网关怎么筛选,可是万人群成员比较多,会导致这个消息包比较大,如果不带成员列表信息到网关,那么要求用户在和网关建立连接的时候,就要把自己加入的群列表信息带过来,绑定到网关,这样逻辑似乎和网关耦合比较严重,老师能详细解释一下么
作者回复: 不需要建连时耦合群信息相关内容,这个问题可以采用分批下发给网关来解决,比如一批100这样。
共 5 条评论7 - 墙角儿的花2019-10-11老师 用websocket做长链接通信在网络较好情况下没什么问题 但在弱网下如2g 3g下就会频繁掉线,但是微信却做的这么好,地铁里仍然很稳定,它走的绝对不是websocket,它怎么做到的这么稳定通畅呢?有什么资料可以查看学习吗。
作者回复: 之前有提到微信手机端应该走的是tcp私有协议,不是websocket。另外你提到的websocket弱网下容易掉线这个得具体case分析一下,不能把这个归结到websocket协议本身,底层一样都是基于tcp来传输的。连接不稳定和很多因素有关,连接入口的是否够快,有没有故障转移通道,能否快速识别到连接断开然后快速进行重连,网络传输的数据是否够小够精简,这些都有关系。微信有一些公开对外演讲的资料,可以查一下。
共 3 条评论5 - clip2019-10-11群聊的私有类型消息是不是要采用补齐而不是剔除的逻辑?因为加了一条仅自己可见的消息给其他人都创建不可见索引就得不偿失了。
作者回复: 嗯,是的,私有消息是聚合,删除是剔除。
共 3 条评论3 - 🐒子2020-04-07老师 你好 我之前也做过im系统 但是在存储部分用 数据库选型有什么推荐吗共 2 条评论2
- 我行我素2019-10-11老师,想请问下:在用户删除消息的时候,把这条被删除消息加入到当前用户和群维度的一个删除索引中,这一步不是很明白
作者回复: 其实就是把群聊消息删除这个单独记录一下,比如一个list里面,key是 uid_群id,value是这个uid在这个群删除的消息id。最后这个用户获取群消息时,从群维度的全量消息里剔除掉这个用户在这个群删除的这些消息id。
共 3 条评论2 - 🐾2019-10-11老师上午好、有些疑惑想跟您确认一下,消息多终端漫游,为解决用户离线期间收不到消息的问题,我们会在服务端按照接收用户维度,暂存用户离线期间的消息,等该用户下次上线时再进行拉取同步。 1、这里的同步,实际上是把服务端的消息同步到客户端,客户端也保存这些消息吧? 2、假如用户重新安装了APP,把客户端保存的数据也清空了,像这种情况下,一般处理是只同步离线消息,不同步历史数据吗? 3、如果客户端不保存消息记录,但又要显示所有历史数据,是不是不需要设计这个离线存储了,直接读取会话维度的所有消息就好?展开
作者回复: 1. 是的。 2. 一般这种情况可以只下推离线消息,历史消息通过用户来触发拉取。 3. 不保存消息记录是指客户端不在本地存储所有消息?这种方式不太好呀,要不没网就看不了所有聊天记录了。
2 - 墙角儿的花2019-10-11群聊信息如果不采用收发箱的方式存储,碰见钉钉这种需要记录查看一条群消息哪些成员已阅,哪些未阅,就无能为力了
作者回复: 这个是个问题,实际上也可以不需要按照uid维度来存储消息,按照消息维度存储已上报过 阅读事件的uid就可以。
共 3 条评论2 - kamida2020-03-14老师 timer和flusher是所有群共用一个吗 那他们是怎么分别track不同的群的呢
作者回复: timer和flusher是共用的,因为加未读是uid维度的,所以最终执行时按照uid来归并就可以了。
1 - yic2019-11-21老师,看了这么多节课程,突然有个问题想问:像微博、微信等这些APP一般的实时在线人数大概是什么量级?一台网关机大概能承载多少在线用户呀?
作者回复: 像微博是千万级在线,微信具体数据不太清楚。单台网关机虽然理论上能到百万级别,但线上一般控制在几十万比较正常,如果是类似直播的业务会控制在更低水平。
1 - leslie2019-10-15其实点对点的在线下推:个人理解就是非常考验中间件存储/数据系统的设计,不合理的设计必然造成某块的负载过大,如何合理的设计和使用这些东西会成为关键。 老师的图中就有MQ和RMDB其实还有Nosql DB:刚好今天李玥老师的MQ刚刚完课,看完了老师的21课反向来学习这课的;看过国内的一些IM,其实这块真实的设计都被隐藏了;个人觉得这块如何修正成为自己的东西如何利用和设计好中间件存储应当是IM设计的一块重点和难点。 IM有听闻说简单的可是老师的课程学到现在:我发现如何合理的设计应用架构、数据系统、以及配合合适的监控应当是系统成败的关键。谢谢老师辛勤的分享以及困惑时的提点和教诲。展开
作者回复: 哈哈,感谢支持和肯定~
1 - 黄海2019-10-14请袁老师看一下这样的方案行吗:把各台网关机上的在线群(在线群成员数>0)的群 uid 作为 key,把网关机的消息队列 topic 作为 value,写入 redis set 中,发送群消息时,根据 key 群 uid 从 redis set 中查出群成员分布在哪些网关机上,然后通过消息队列,精准的向这些网关机推送群聊消息
作者回复: 这个方案的问题在于:群聊的使用场景并不存在说“某个用户在某个群在线”这么个说法,和直播的房间概念是不一样的。可以认为只要用户上线就应该处理所有群的消息。
共 5 条评论1 - 木槿花开2019-10-11万人群聊,系统是维护了万个TCP链接吗?
作者回复: 这里的意思是一个群有一万人的这种超大规模群。只有在线的用户才会建立长连
共 3 条评论1 - pdf2022-02-18老师,如果群消息删除使用另外一个表记录删除操作,在没有连表的情况下该怎么查询呢?
- pdf2022-02-16老师,各位同学。 如果消息按天分表,某天群解散的时候,这个消息删除怎么实现比较好呢?
- Geek_d18bea2021-11-24原文提到: 假设查询到这个群一共有 3 人,除去发送方用户 A,还有用户 B 和用户 C。 然后业务逻辑处理层把消息扇出到『接收人维度』,投递到全局的消息队列中;…… 接着,各网关机把归属本机的用户的消息,通过长连下推下去。 万人群的消息推送,假设群里除了发送者,还有 10000 人。则业务层需要发 10000 条消息到 mq。 gid1, msg1, uid1 gid1, msg1, uid2 gid1, msg1, uid3 … gid1, msg1, uid10000 同问这个问题,请问老师是这样一个群消息,扇出多个mq消息吗?展开
- 土娃娃2021-02-01群成员基础数据的存储缓存结构用什么呢?进群和退群时怎么对缓存进行处理。如何根据版本号获取到删除的成员,例如:如果用redis的SortedSet,是用一个set保持所有的成员增删的版本号(这样set会变得很大,如果频繁有人退群的话)?还是用两个set,其中一个保存当前群的所有有效成员,另外一个保存删除的成员,按版本号获取的时候对两个set中的结果进行合并?
- 唯我天棋2020-12-11老师,一般用什么存储去存群成员关系比较合适。 用mysql存,查询有性能问题。 用redis存 zset + hash,需要保证数据一致性。而且redis不支持条件查询,比如想查所有管理员。 而且,比如一个6000人的群,拉取群列表,性能压力特别大。
- 倔强小德普2020-05-28由各网管机维护数据,这个数据读的是哪边的?如果是本地内存 节点挂了 咋办
- 李先生2020-04-10有个问题:对于直播间场景,网关机(im客户端)维护长链接和用户信息,假如一场直播持续1小时,直播累计uv是300万,直播同时在线uv是100万,需要对网关机进行扩容,比如使用32g的服务器,需要多少台网关机才可能使直播正常进行,还有弹幕的发送与下推应如何处理呢(为了保证弹幕的实时性,是否可以直接展示,异步存储弹幕呢)?