默认
打赏 发表评论 13
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
网易云信技术分享:IM中的万人群聊技术方案实践总结
阅读(126011) | 评论(13 收藏13 淘帖1 6
微信扫一扫关注!

本文来自网易云信团队的技术分享,原创发表于网易云信公众号,原文链接:mp.weixin.qq.com/s/LT2dASI7QVpcOVxDAsMeVg,即时通讯网收录时有改动。


1、引言


在不了解IM技术的人眼里,群聊是再平常不过的功能而已,万人群聊?应该也不难实现吧?!

确实,从前端功能界面上来看,群聊无非就是个循环向群员发送消息的一对多聊天消息分发模式而已,难在何处?

真实的情况是,群聊是IM系统中的高难度技术点之一。难在哪?难在服务端!从某种角度上说,群聊功能的架构设计和技术实现的品质,可以代表这款IM软件的技术水平。

群聊从后台的技术实现上说,至少有以下难点:

  • 1)如何高效地进行大量群员消息的分发?
  • 2)如何高效地管理群员的在线状态?
  • 3)如何高效地读取群员的在线状态?
  • 4)集群系统中,如何高效地保证群员消息的准确送达?
  • 5)群聊消息该扩散写还是扩散读?
  • 6)如何保证大量群聊消息分发的情况下不影响单聊消息体验?
  • 7)如何应对大群突发事件下的性能负载?
  • .... ....

目前,市面上主流的IM产品中,微信群是500人上限,QQ群是3000人上限(3000人群是按年付费升级,很贵,不是为一般用户准备的)。一方面,从产品的定义上群成员数量不应过多,另一方面,技术成本也是个不可回避的因素。万人群这种超大规模群的技术难度,更是难已想象。

本文内容是网易云信团队为了响应万人群聊功能需求,在设计实现万人群聊技术方案中总结的技术实践,借此机会分享给各IM开发者同行。

网易云信技术分享:IM中的万人群聊技术方案实践总结_timg.jpeg

万人群聊相关文章推荐阅读:


网易技术团队分享的其它文章:


2、概述


随着移动互联网的发展,即时通讯服务被广泛应用到各个行业,客户业务快速发展,传统百人或千人上限的群聊已经无法满足很多业务发展需求,因此网易云信IM推出万人群服务。

万人群场景需要解决以下问题:

  • 1)消息需要按1:9999的比例进行转发投递,按常规消息处理流程将产生大量的子任务,对系统吞吐量的要求极高;
  • 2)在微服务系统架构下,如果不采用一些优化方案,服务以及存储(DB、缓存等)之间的QPS和网络流量将非常高;
  • 3)以群为单位的缓存(如群成员列表)内存存储开销较大(假设一个成员200Byte,万人群约2MB);
  • 4)群成员登录后需要同步群离线消息,智能手机上App前后台切换产生的较多登录同步消息协议,因此需要优化消息同步方案。

为了解决以上问题,万人群技术方案采用了“聚合+分层/组+增量”的设计思路:
网易云信技术分享:IM中的万人群聊技术方案实践总结_1.png

3、万人群消息的处理流程


1)按群维护在线群成员信息,主要包含两部分(可以理解为两个缓存集合):

  • a. 群成员在线信息:即用户在线状态变化(上线、下线)时,更新相应群的在线状态信息(即动态维护群有哪些成员在线);
  • b. 成员IM长连接信息:即用户新登录时,更新用户的Link信息(即登录所在Link的地址信息,消息转发时根据Link地址路由消息)。

2)IM Server收到群消息后,按群ID将消息路由到“群消息服务”模块;

3)群消息模块检查并预处理消息内容,然后通过“群成员在线状态”服务获取在线成员,完成消息转发的基础工作。为了减少群消息模块和群在线成员服务之间的网络流量,采用了“本地缓存+增量同步”的缓存策略,即本地缓存记录最后更新版本号和时间戳,每次同步群在线成员前先检查缓存版本号是否有变更,若有则按最后更新时间增量同步;

4)通过“群成员在线服务”获取在线群成员的Link链接信息,按Link分组路由消息(分组路由的原因:同一Link上的全部群成员只需要路由一条消息即可)。同样为了减少网络开销,成员Link信息也采用“本地缓存+增量同步”的方案;

5)群消息采用“漫游+历史”的存储方案,漫游的消息存储在分布式缓存中,历史消息异步写入HBase。用户登录后可以通过漫游快速的获取到最新消息,并可以通过拉取历史查看更早的消息。

4、万人群方案本地缓存增量同步策略


抛开群在线状态管理逻辑,群成员在线状态服务可以简单理解为分布式集中缓存。

增量同步技术方案如下:
网易云信技术分享:IM中的万人群聊技术方案实践总结_2.png

如上图所示:

  • 1)数据缓存是一个集合,其包含了多个缓存数据项,每一个数据项带有最后更新时间信息;另外缓存还有一个严格递增的版本号;
  • 2)缓存数据变更(新增、修改、删除)后,需要增加版本号;
  • 3)本地线程通过缓存管理读取数据时,管理服务先检查本地版本号和分布式缓存中的版本号是否一致,若不一致则按本地最新时间戳增量同步新数据项,并更新本地的版本号和最后更新时间(为了避免分布式集中缓存中并发写入导致的增量时间戳不可靠问题,增量更新时可以将本地记录的最后更新时间戳向前推移,比如减少20ms);
  • 4)为避免本地多线程并发读取相同数据项导致并发更新本地缓存的问题,可以按缓存数据合并更新请求,即解决并发问题还可以减少网络开销;
  • 5)缓存数据由大量数据项构成,为了避免单个缓存数据太大,可以将数据项中的属性业务场景精简(冷热分离),低频次读写的属性额外缓存。

5、万人群水平扩容方案


万人群采用大量本地缓存的方案解决消息处理性能和网络流量的问题,因此本地存储空间成了方案的瓶颈点。因此我们设计了分组路由的技术方案。

网易云信技术分享:IM中的万人群聊技术方案实践总结_3.png

消息按群ID和路由策略定向路由到指定分组(集群)上处理,分组由多个计算节点组成,因此方案上可以做到分组内和分组间的水平扩缩容。

6、作为“云”服务,网易云信是如何实现万人群所需的计算资源的?


由于万人群对计算和存储资源消耗比较高,在实施和运维方案上也有一定的特殊性,为了保证业务的可靠性和稳定性,网易云信是将万人大群的能力,仅提供给专属的云客户(普通公有云客户是无法使用的)。

之所以能从软硬件基础设施上为万人群提供保障,网易云信的IM专有云必须具备以下资源能力:

  • 1)需要专属的独立计算资源:保持计算资源独立,且资源冗余度比公有云高,且需要保证不会受到公有云上其他客户业务的影响;
  • 2)需要专属的独立运维服务:从而根据客户业务场景制定最佳的业务监控、弹性扩容、故障迁移等运维方案。

总之,万人群聊的实现,过硬的技术方案设计和技术实现只是一方面,基础计算设施资源和运维能力也是不可或缺。

所以,从今以后,不要随随便便就喊万人群聊,甚至十万人群聊,这不是想实现就能实现的哦!

附录:更多群聊相关技术文章


快速裂变:见证微信强大后台架构从0到1的演进历程(一)
如何保证IM实时消息的“时序性”与“一致性”?
IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?
IM群聊消息如此复杂,如何保证不丢不重?
微信后台团队:微信后台异步消息队列的优化升级实践分享
移动端IM中大规模群消息的推送如何保证效率、实时性?
现代IM系统中聊天消息的同步和存储方案探讨
关于IM即时通讯群聊消息的乱序问题讨论
IM群聊消息的已读回执功能该怎么实现?
IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?
一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践
[技术脑洞] 如果把14亿中国人拉到一个微信群里技术上能实现吗?
IM群聊机制,除了循环去发消息还有什么方式?如何优化?
网易云信技术分享:IM中的万人群聊技术方案实践总结
>> 更多同类文章 ……

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:求助公司自己搭建了IM应用,iOS端消息推送部分该如何实现?下一篇:[已回复] 求助关于MobileIMSDK如何消息加密的问题

本帖已收录至以下技术专辑

推荐方案
评论 13
万人群会不会刷屏太厉害看都看不清?
签名: 秋天到了,终于凉快了
不会!刷到哪里更新到哪里!不会一下子刷完!
学习
如果能讲的再细致一点就更好了
签名: now start 。。。
引用:妮子 发表于 2019-12-12 23:16
如果能讲的再细致一点就更好了

都是点到为止的,有些东西再深入就涉及商业竞争力了
引用:JackJiang 发表于 2019-12-13 10:22
都是点到为止的,有些东西再深入就涉及商业竞争力了

明白,明白
签名: now start 。。。
这里有个疑问,如果一个人大多个群中,这里都要维护一个人在所有的群里的在线状况的二级缓存,怎么保让这个数据的准确性的,我理解 一个人上线 ,需要遍历这个人所有的群信息,下线也是一样,被拉入新群也是一样,遍历所有群成员后才能缓存。
引用:sulo_xxr 发表于 2020-04-20 16:12
这里有个疑问,如果一个人大多个群中,这里都要维护一个人在所有的群里的在线状况的二级缓存,怎么保让这个 ...

“用户在线状态”,和该用户在群里面没有关系吧? 我理解的“IM用户在线就是TCP状态在open的时候就是在线,否则就是离线”,用户加入了100个群,并且用户有1000个好友的情况,用户每次在线,或者离线的时候,就要发100+1000(假设1000个好友都在线,如果 只有10个好友在线的话,就是 100 + 10)条小消息
引用:sulo_xxr 发表于 2020-04-20 16:12
这里有个疑问,如果一个人大多个群中,这里都要维护一个人在所有的群里的在线状况的二级缓存,怎么保让这个 ...

真实场景中,一个人所在的万人大群一定是有限的,比如10个。这些大群因为特殊性,存储时和普通群做区分。A登录时,只捞他所在的大群gid1,gid2,...gid10这样,redis来个sadd操作。A离线时,同样,删除操作
请问路由模块每次下发数据都需要查询在线状态服务吗,玩意遇到那种万人群,岂不是要查一万次。。。 网络消耗会非常离谱
5)群消息采用“漫游+历史”的存储方案,漫游的消息存储在分布式缓存中,历史消息异步写入HBase。用户登录后可以通过漫游快速的获取到最新消息,并可以通过拉取历史查看更早的消息。


为什么漫游消息和历史消息共用一块存储啊 ,也就是漫游消息也读hbase
引用:yqfclid 发表于 2022-06-17 15:38
请问路由模块每次下发数据都需要查询在线状态服务吗,玩意遇到那种万人群,岂不是要查一万次。。。 网络消 ...

是增量哦
引用:mayongjian 发表于 2022-09-04 21:17
5)群消息采用“漫游+历史”的存储方案,漫游的消息存储在分布式缓存中,历史消息异步写入HBase。用户登录 ...

你的理解不对吧,这句“漫游的消息存储在分布式缓存中,历史消息异步写入HBase”,不是明明说清楚了吗
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部