IM技术分享:万人群聊消息投递方案的思考和实践
本文由融云技术团队原创分享,原题“技术实践丨万人群聊的消息分发控速方案”,为使文章更好理解,内容有修订。
1、引言
传统意义上的IM群聊,通常都是像微信这样的500人群,或者QQ的2000人群(QQ有3000人群,但那是单独收费的,也就意味着它并非无门槛标配,能用上的人并不多)。
自从国外某号称“世界上最安全的IM”搞出万人群聊之后,万人群迅速被国内的使用者们接受。伴随着移动互联网的发展,即时通讯服务被广泛应用于各个行业(以经不再局限于传统IM社交应用领域),随着业务快速发展,传统百人、千人上限的群聊已经无法满足很多业务场景需求,所以万人甚至十万人的超大群也算是相伴而生、顺应潮流。

▲ “纸飞机”的万人群(开发人员颤抖中...)
IM群聊一直是IM应用中比较有难度的热点技术之一,通常意义的群聊,无非就是500人群、1000人群、2000人群这样,技术实现上比单聊要复杂不少。然而对于万人群聊(甚至十万人群聊)来说,相比百人、千人群聊,技术实现上那几乎是另一个技术维度的事情,难度要高很多。
本文根据融云技术团队的实践经验,总结了万人群聊消息投递方案的一些思考和实践,希望能给你带来启发。
学习交流:
- 即时通讯/推送技术开发交流5群:215477170 [推荐]
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK
(本文同步发布于:http://www.52im.net/thread-3687-1-1.html)
2、相关文章
万人群聊有关的技术文章还可读一读以下这篇:
融云技术团队分享的其它文章:
- 《融云技术分享:融云安卓端IM产品的网络链路保活技术实践》
- 《融云技术分享:全面揭秘亿级IM消息的可靠投递机制》
- 《融云技术分享:基于WebRTC的实时音视频首帧显示时间优化实践》
- 《IM消息ID技术专题(三):解密融云IM产品的聊天消息ID生成策略》
3、超大群面临的技术挑战
与百人群、千人群相比,万人、甚至十万人超大群,大幅提升了群的触达人数,对于很多业务场景来说,好处不言而喻。
然而单群成员如此之大,给 IM 系统的流量冲击非常巨大,技术难度可想而之。我们先来分析一下超大群的技术挑战。
以一个万人群的模型为例:
- 1)如果群中有人发了消息,那么这条消息需要按照 1:9999 的比例进行分发投递,如果我们按照常规消息的处理流程,那么消息处理服务压力巨大;
- 2)消息量大的情况下,服务端向客户端直推消息的处理速度将会成为系统瓶颈,而一旦用户的消息下发队列造成了挤压,会影响到正常的消息分发,也会导致服务缓存使用量激增;
- 3)在微服务架构中,服务以及存储(DB,缓存)之间的 QPS 和网络流量也会急剧增高;
- 4)以群为单位的消息缓存,内存和存储开销较大(消息体的存储被放大了万倍)。
基于这些技术挑战,要想真正达成超大群的技术目标,势必要做特定的技术优化来应对。
4、一般群聊的消息投递模型
先来看看普通群聊的消息投递模型。
我们的普通群聊消息投递模型如下图所示:

如上图所示,当用户在普通群里发了一条消息后,投递路径是:
- 1)消息先到群组服务;
- 2)然后通过群组服务缓存的群关系,锁定这条消息最终需要分发的目标用户;
- 3)再根据一定的策略分发到消息服务上;
- 4)消息服务再根据用户的在线状态和消息状态来判断这条消息是直推、通知拉取还是转 Push,最终投递给目标用户。
普通群聊的消息投递,正像您期待的那样,基本上大家的实现手段都大差不差。然而对于万人群来说,这显然还不够。
下面来看看我们针对万人群聊消息投递的技术优化手段。
5、万人群聊消息投递优化手段1:控速
针对万人群的消息投递,我们的一个主要手段就是控速。

如上图所示。
首先:我们会根据服务器的核数来建立多个群消息分发队列,这些队列我们设置了不同的休眠时间以及不同的消费线程数。
通俗来讲,可以将队列这样划分为快、中、慢等队列。
其次:我们根据群成员数量的大小来将所有群映射到相应的队列中。
规则是:
- 1)小群映射到快队列中;
- 2)大群映射到相应的慢队列中。
然后:小群由于人数少,对服务的影响很小,所以服务利用快队列快速的将群消息分发出去,而大群群消息则利用慢队列的相对高延时来起到控速的作用。
6、万人群聊消息投递优化手段2:合并
在本文第3节中提到的万人群聊所面临的技术挑战,最主要的挑战其实就是消息进行扩散分发投递后,消息被克隆出N条,消息流量瞬间被放大。
举个例子:当一条群消息发送到 IM 服务器后,需要从群组服务投递给消息服务,如果每一个群成员都投递一次,并且投递的群消息内容是一致的话,那肯定会造成相应的资源浪费和服务压力。
那么针对这种情况,我们的解决方案就是进行消息合并投递。
原理就是:服务落点计算中我们使用的是一致性哈希,群成员落点相对固定,所以落点一致的群成员我们可以合并成一次请求进行投递,这样就大幅提高了投递效率同时减少了服务的压力。
下图是云信团队分享的万人群消息合并投递逻辑:

▲ 上图引用自《IM中的万人群聊技术方案实践总结》
如上图所示,云信团队的万人群消息合并投递方案是:按Link分组路由消息,同一Link上的全部群成员只需要路由一条消息即可。
7、十万、百万级的超大群处理方案
在实际群聊业务中,还有一种业务场景是超大规模群,这种群的群人数达到了数十万甚至上百万。
这种群如果按照上述的投投递方案,势必仍会造成消息节点的巨大压力。
比如我们有一个十万人的群,消息节点五台,消息服务处理消息的上限是一秒钟 4000 条,那每台消息节点大约会分到 2 万条群消息,这已大大超出了消息节点的处理能力。
所以为了避免上述问题,我们会将群成员上线超过3000的群识别为万人群、超级群,这种级别的群可以根据服务器数量和服务器配置相应做调整针对这种超级群会用特殊的队列来处理群消息的投递。
这个特殊的队列1秒钟往后端消息服务投递的消息数是消息服务处理上限的一半(留相应的能力处理其他消息),如果单台消息服务处理的 QPS 上限是 4000,那群组服务一秒往单台消息服务最多投递 2000 条。
8、写在最后
未来,我们也会针对群消息进行引用投递,对于大群里发的消息体比较大的消息,我们给群成员只分发和缓存消息的索引,比如 MessageID。等群成员真正拉取群消息时再从将消息组装好给客户端分发下去。这样做会节省分发的流量以及存储的空间。
随着互联网的发展,群组业务的模型和压力也在不停地扩展,后续可能还会遇到更多的挑战,当然也会不断迭代出更优的处理方式来应对。
附录:更多IM群聊技术文章
《IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?》
《一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践》
《[技术脑洞] 如果把14亿中国人拉到一个微信群里技术上能实现吗?》
《阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处》
《直播系统聊天技术(一):百万在线的美拍直播弹幕系统的实时推送技术实践之路》
《直播系统聊天技术(二):阿里电商IM消息平台,在群聊、直播场景下的技术实践》
《直播系统聊天技术(三):微信直播聊天室单房间1500万在线的消息架构演进之路》
《直播系统聊天技术(四):百度直播的海量用户实时消息系统架构演进实践》
《企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等》
>> 更多同类文章 ……
本文已同步发布于“即时通讯技术圈”公众号。
IM技术分享:万人群聊消息投递方案的思考和实践的更多相关文章
- 网易云信技术分享:IM中的万人群聊技术方案实践总结
本文来自网易云信团队的技术分享,原创发表于网易云信公众号,原文链接:mp.weixin.qq.com/s/LT2dASI7QVpcOVxDAsMeVg,收录时有改动. 1.引言 在不了解IM技术的人眼 ...
- 技术分享预告丨k3s在边缘计算中的应用实践
技术分享是在[Rancher官方微信技术交流群]里以图文直播+QA实时互动的方式,邀请国内已落地经验的公司或团队负责人分享生产落地的最佳实践.记得添加微信小助手(微信号:rancher2)入群,实时参 ...
- 阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处
本文引用了唐小智发表于InfoQ公众号上的“钉钉企业级IM存储架构创新之道”一文的部分内容,收录时有改动,感谢原作者的无私分享. 1.引言 业界的 IM 产品在功能上同质化较高,而企业级的 IM 产品 ...
- 腾讯QQ内测群新功能:QQ万人群即将袭来!
4月6日早晨有人爆出QQ群正在内部测试QQ万人群的消息,此消息一出,网友们都不蛋定了,各种议论纷纷,可是唯独腾讯没有做出任何有关这方面的解释. QQ是要准备让上万个人在一个群聊天吗? 那不会被刷屏刷死 ...
- kafka技术分享02--------kafka入门
kafka技术分享02--------kafka入门 1. 消息系统 所谓的Messaging System就是一组规范,企业利用这组规范在不同的系统之间传递语义准确对的消息,实现松耦合的异步数据 ...
- 微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)
1.点评 对于IM系统来说,如何做到IM聊天消息离线差异拉取(差异拉取是为了节省流量).消息多端同步.消息顺序保证等,是典型的IM技术难点. 就像即时通讯网整理的以下IM开发干货系列一样: <I ...
- 融云技术分享:解密融云IM产品的聊天消息ID生成策略
本文来自融云技术团队原创分享,原文发布于“融云全球互联网通信云”公众号,原题<如何实现分布式场景下唯一 ID 生成?>,即时通讯网收录时有部分改动. 1.引言 对于IM应用来说,消息ID( ...
- 知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路
本文来自知乎官方技术团队的“知乎技术专栏”,感谢原作者陈鹏的无私分享. 1.引言 知乎存储平台团队基于开源Redis 组件打造的知乎 Redis 平台,经过不断的研发迭代,目前已经形成了一整套完整自动 ...
- 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)
RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三 多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...
- 融云技术分享:融云安卓端IM产品的网络链路保活技术实践
本文来自融云技术团队原创分享,原文发布于“ 融云全球互联网通信云”公众号,原题<IM 即时通讯之链路保活>,即时通讯网收录时有部分改动. 1.引言 众所周知,IM 即时通讯是一项对即时性要 ...
随机推荐
- 云原生爱好者周刊:这款支持全平台的 Podman Desktop 值得一试
开源项目推荐 Podman Desktop Companion Podman 桌面客户端,支持 macOS.Windows 和 Linux 平台,后端支持原生 Podman(仅支持 Linux).Po ...
- 放大招!青云企业级容器平台 QKCP 迎来重磅升级
青云企业级容器平台 QKCP 3.2 重磅发布.QKCP(QingCloud KubeSphere Container Platform)是青云科技基于 KubeSphere 开源容器平台打造的企业级 ...
- c++11大括号初始化
C++11可以将{}初始化器用于任何类型(可以用等号,也可以不用) 数组.集合初始化 在C++11中,集合(列表)的初始化已经成为C++的一个基本功能,被称为"初始化列表": // ...
- bresenham算法(贝汉明算法)
- 使用NodeJS 搭建 Vue + TypeScipt 快速构建工具
使用 NodeJS 搭建 Vue + TypeScipt 快速构建工具 前言: 为保证使用 Typescript 开发 Vue 的规范性和开发效率,添加组件.页面.路由.store 的时候尽量使用工具 ...
- SQL Server 数据太多如何优化
大家好,我是 V 哥.讲了很多数据库,有小伙伴说,SQL Server 也讲一讲啊,好吧,V 哥做个听话的门童,今天要聊一聊 SQL Server. 在 SQL Server 中,当数据量增大时,数据 ...
- 0.1 Introduction to the tenth anniversary edition
此序作于2010年 1970s&1980s, 除了将量子系统仅仅视为一种自然界中需要解释的现象,大家开始将其视为可以设计的系统. 这种新的观点引起了物理,计算机科学和信息理论等领域交叉融合之后 ...
- 关于MNN工程框架编译出来的静态库和动态库的使用
一.MNN.lib文件路径 如果你看过之前的博客内容,应该可以在编译的的工程当中 C:\Users\Administrator\Desktop\MNN\MNN-master\MNN-CPU-OPENC ...
- 细说MySql索引原理
MySQL索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 可以类比字典,如果要查"mysql"这个单词,我们肯定需要定位 ...
- OSG开发笔记(三十一):OSG中LOD层次细节模型介绍和使用
前言 模型较大的时候,出现卡顿,那么使用LOD(细节层次)进行层次细节调整,可以让原本卡顿的模型变得不卡顿. 本就是LOD介绍. Demo LOD 概述 LOD也称为层次细节模 ...