乐趣区

关于微信:微信团队分享微信直播聊天室单房间1500万在线的消息架构演进之路

本文由微信开发团队工程师“kellyliang”原创发表于“微信后盾团队”公众号,收录时有订正和改变。

1、引言

随着直播和类直播场景在微信内的增长,这些业务对长期音讯(在线状态时的实时音讯)通道的需要日益增长,直播聊天室组件应运而生。直播聊天室组件是一个基于房间的长期音讯信道,次要提供音讯收发、在线状态统计等性能。

本文将回顾微信直播聊天室单房间海量用户同时在线的音讯组件技术设计和架构演进,心愿能为你的直播聊天互动中的实时聊天音讯架构设计带来启发。

本文已同步公布于“即时通讯技术圈”公众号,欢送关注。公众号上的链接是:点此进入。

2、相干文章

  • 《腾讯 QQ1.4 亿在线用户的技术挑战和架构演进之路 PPT》
  • 《挪动端 IM 中大规模群音讯的推送如何保障效率、实时性?》
  • 《古代 IM 零碎中聊天音讯的同步和存储计划探讨》
  • 《以微博类利用场景为例,总结海量社交零碎的架构设计步骤》
  • 《一套高可用、易伸缩、高并发的 IM 群聊、单聊架构方案设计实际》
  • 《阿里技术分享:电商 IM 音讯平台,在群聊、直播场景下的技术实际》
  • 《[一个 WebSocket 实时聊天室 Demo:基于 node.js+socket.io [附件下载]](http://www.52im.net/thread-51…》

3、1500 万在线的挑战

视频号直播上线后,在产品上提出了直播后盾须要有单房间撑持 1500w 在线的技术能力。接到这个我的项目的时候,自然而然就让人联想到了一个十分乏味的命题:能不能做到把 13 亿人拉个群?

本文将深入浅出地介绍聊天室组件在演进过程的思考,对这个命题做进一步对摸索,尝试提出更靠近命题答案的计划。

4、直播聊天室 1.0 架构


如上图所示,能够看到直播聊天室 1.0 架构还比拟原始和间接,没有太多简单的技术利用。
这套架构诞生于 2017 年,次要服务于微信电竞直播间,外围是实现高性能、高实时、高可扩大的音讯收发架构。

5、音讯扩散计划选型:读扩散


微信中规范的群音讯应用的是写扩散机制,而直播聊天室跟微信规范群聊有着微小的差别。
而且,对于同一人而言,同一时间只能关注一个聊天室,决定了直播聊天室中的音讯扩散计划应该应用读扩散的机制。

6、longpolling(长轮询)机制


为了让用户须要实时同步到新音讯,咱们采纳的是 longpolling 模式
很多人会纳闷为什么不必 websocket,起因有 3 个:

  • 1)websocket 次要思考推模式,而推模式则有可能丢,做到不丢还是有须要拉模式来兜底;
  • 2)推模式下,须要精准保护每个时刻的在线列表,难度很大;
  • 3)longpolling 实质是一个短连,客户端实现更简略。

7、无状态 cache 的设计

很显著,单纯的读扩散,会造成微小读盘的压力。依照国际惯例,这里理所应当地减少了一个 cache,也就是下面架构图中的 recvsvr。

一般的 cache 都是有状态的、可穿透的,对常常会呈现突发流量的聊天室不是特地敌对。而通过异步线程工作,恰好能够解决这两个点。

① 实时告诉:发送音讯时,在写入列表后,向 recvsvr 集群发送告诉。
② 异步拉取:recvsvr 机器收到告诉后,触发异步线程拉取。
③ 兜底轮询:当 recvsvr 机器上接管到某个聊天室的申请时,触发该聊天室的轮询,保障 1s 内至多拜访一次音讯列表,防止告诉生效导致无奈更 cache,同时做到机器启动时数据的主动复原:

④ 无锁读取:通过读写表拆散和原子切换,做到音讯的无锁读取:

⑤ sect 化部署:群数量增多时,扩 sect 能够把群摊派到新的 sect 上。
无状态音讯 cache 的设计,不仅极大地提高了零碎的性能,而且帮忙聊天室建设了一个高扩展性音讯收发架构。

8、技术痛点


只管做到了高性能的音讯收发,1.0 版本却并不能实现单房间 1500w 同时在线的指标。
通过对整个架构和逻辑进一步的剖析,咱们发现 4 个妨碍咱们后退的痛点:

  • 1)大直播间里,音讯信道不保障所有音讯都下发,连麦胜利信令失落会使得连麦性能不可用,大礼物打赏动画信令失落会带来客诉;
  • 2)一个房间的在线列表,是由 recvsvr 把最近有收取该房间的音讯的 user 聚合到同一台 statsvr 失去的,有单点瓶颈,单机失败会导致局部房间在线数跳变、在线列表和打赏排行榜不可用等;
  • 3)没有提供历史在线人数统计性能;
  • 4)裸的 longpolling 机制在音讯始终有更新的状况下,无法控制申请量。

9、直播聊天室 2.0 架构


从下面剖析的痛点,咱们得出了聊天室 2.0 须要解决的问题:

  • 1)解决丢重要信令问题,保障热点拜访下性能的可靠性;
  • 2)解决在线统计的单点瓶颈,保障热点拜访下在线统计模块的可扩展性;
  • 3)实现一个高效精确的历史在线统计,保障大数据量下统计的高性能和准确性;
  • 4)灵便把控流量,进一步晋升隔离和容灾能力,保障热点拜访下零碎的可用性。

10、优先级音讯列表


丢信令的实质起因:recvsvr 只保留最近 2000 条音讯,大直播间里,有些音讯客户端还没来的及收就被 cache 淘汰了。
在聊天室 1.0 版本,咱们曾经证实了写扩散不可行,因而这里也不可能通过写扩散解决。

另外一个比拟直观的计划:是将重要的零碎信令写到另外一个列表外面,recvsvr 同时读取两个音讯表。带来的耗费是 recvsvr 对 kv 层减少将近一倍的访问量。于是,咱们思考有没有更优的计划。

回到 1.0 版本的一个计划细节:咱们能够看到大部分状况下,当新音讯到来的时候,recvsvr 它都是能及时感知到的,因而 recvsvr 一次拉取到的音讯条数并不会很多,因而这一步骤上不会丢音讯。
所以咱们是能够把音讯表这个操作收归到 recvsvr 外面的:

① 打优先级标记:仍然只写一张音讯表,给重要的信令打上优先级标记。(目标:节俭 RPC 耗费)
② cache 内分表:recvsvr 拉到音讯后离开一般音讯列表和重要音讯列表;(目标:最小化改变)
③ 优先收取:收取时候 normal seq 和 important seq,先收重要音讯表,再收取一般音讯表。(目标:优先下发)
通过一个简略的优化,咱们以最小的革新代价,提供到了一条牢靠的重要音讯信道,做到了连麦和大礼物动画的零失落。

11、分布式在线统计

11.1 写共享内存,主从互备


参考微信设施在线模块,咱们能够有这个一个计划:

  • ① 分 sect,一个直播间选一个 sect;
  • ② 按 roomid 选一台机作为 master,读写该机器的共享内存;
  • ③ master 把这个 roomid 的数据同步到 sect 内其它机器,master 挂了的状况能够选其它机器进行读写。

上述计划的优缺点:

  • 1)长处:解决了换机跳变问题。
  • 2)毛病:主备同步计划简单;读写 master,大直播间下仍然有单机热点问题。

论断:用分布式存储作为数据的核心节点。

11.2 写 tablekv

如上图所示:

  • ① 用 tablekv 的一个表来存在线列表,每行记录用户 id 和沉闷工夫;
  • ② 定期更新用户的心跳工夫,保护在线。

上述计划的优缺点:

  • 长处:解决了换机跳变问题,数据做到了分布式;
  • 毛病:1500w 在线 10s 心跳一次 => 9000w/min,穿透写单表有并发和性能问题;离线不会实时从磁盘删数据,历史沉闷人数远大于以后在线,造成数据冗余。

逐点击破,单 key 是能够通过拆 key 来解决的,数据冗余能够通过 key-val 存储做全量替换解决,而穿透问题其实能够参考 recvsvr 的实现形式。
因而,咱们失去一个比拟好的计划:拆 key + 读写拆散 + 异步聚合落盘。

① 散布统计 :

  • (1) 每台机负责局部在线统计;
  • (2) 每台机内按 uin 哈希再分多 shard 打散数据;
  • (3) 每个 shard 对应 kv 的一个 key;


② 组合数据:让每台机都拉取所有 key 的数据,组合出一个残缺的在线列表:

③ 异步聚合更新:心跳只更新内存,异步工作清理离线用户,并把列表序列化到一个 key 的 val。
④ 异步拉取:由异步工作来执行②的拉取和组合数据。
⑤ 原子切换:残缺的在线列表做双指针,利用原子操作无锁切换,做到无锁查问。
由此,咱们进步了心跳更新和在线查问的性能,做到了在线统计模块的分布式部署和可平行扩大。

12、基于 hyperloglog 的历史在线统计

12.1 需要

历史在线统计,是要已经看过该直播的用户数 uv,在产品上的体验就是视频号直播的“xxx 人看过”。
在分布式在线统计的章节,咱们曾经谈到了,用 tablekv 来记录成员列表是不太可行的。

另外一个想法:是利用 bloomfilter 做数据压缩和去重统计,额定去保护一个 count 做累加。
那么这里有两点:

  • 一是 bloomfilter 和 count 之间要思考一致性问题;
  • 二是 bloomfilter 准确率跟压缩率相干,较好的准确率还是须要比拟大的数据量。

于是咱们调研了业界的一些 uv 统计计划,最终找到了 redis 的 hyperloglog,它以极小的空间复杂度就能做到 64 位整形级别的基数估算。

12.2 hyperloglog 是什么?

hyperLogLog 是一种概率数据结构,它应用概率算法来统计汇合的近似基数,算法的最根源则是伯努利过程。

伯努利过程:设一个硬币背面为 0,侧面为 1,抛一枚硬币直到后果为 1 为止。
如果做 n 次伯努利试验,记录每次伯努利过程须要抛硬币的次数为 Ki,则能够估算:_n=2^Kmax_。

hyperloglog 对 Kmax 的计算进行了分桶和和谐平均值优化,使得在准确率比裸的伯努利估算要高。
优化的次要内容:

  • ① 将要统计的数据 hash 成一个 64 位整形;
  • ② 用低 14 位来寻找桶的地位;
  • ③ 剩下的高位里寻找第一个 1 呈现的地位,作为上述伯努利过程的 Ki;
  • ④ 对桶的值进行更新 Rj = max(Rj, Ki);
  • ⑤ 估算时,对各个桶的值算和谐平均值 DV 来代替上述的 Kmax。

从上述算法的形容来看:hyperloglog 无非就是存了 m 个桶的数值(_m=10000+_),原本空间复杂度也不高了。再通过一些位压缩,hyperloglog 把整个数据结构优化到了最大空间复杂度为 12K。

12.3 tablekv+hyperloglog 并行不悖

因为 hyperloglog 产生的毕竟是近似值,基数较少的时候误差会更显著,所以咱们能够用 tablekv 来补全历史在线数较小时的体验。

  • ① 历史在线数较小时,双写 tablekv + hyperloglog,以 tablekv selectcount 为准;
  • ② 历史在线数较大时,只写 hyperloglog,以 hyperloglog 估算值为准;
  • ③ 在线统计模块定期把在线列表 merge 到 hyperloglog 防止丢数据。

最终咱们达到的成果是:历史在线不超过 1w 时齐全精确,超过 1w 时准确率大于 95%。

13、流量隔离 vipsect


大家都晓得:大直播间会带来爆发式的申请量,咱们不能让大直播间引起的失败影响占大多数的小直播间。
另外:大直播间影响力大,也要去保障它的良好体验,那须要用比小直播间更多的机器去撑持。
而且:聊天室对 kv 层的申请数,跟机器数成正比,小直播间在多机器下会造成大量不必要的耗费。
对于这种状况:咱们参考了微信领取应答大商户和小商户的办法,流量隔离,在聊天室的里设立 vip sect。

如上图所示:

  • ① 对可预测的大直播提前加白,间接走 vip sect;
  • ② 其它直播直走一般 sect;
  • ③ 大小直播策略分级,大直播在线列表才拆 key。

尽管还有些依赖经营,然而通过这种形式,咱们切走大部分的大直播流量,也升高了整个系统对 kv 层的压力。
那么:为什么不做主动切 vip sect ?
这是一个 future work,目前有了一些初步计划,还须要去验证切换过程带来影响,进一步细化策略,也欢送大家提出贵重倡议。

14、主动柔性下的流量把控


在 longpolling(长轮询)的机制下(见本文第 6 节),直播间始终有音讯的话,100w 的在线每分钟至多会产生 6kw/min 的申请,而 1500w 更是高达 9 亿 /min。logicsvr 是 cpu 密集型的服务,按 30w/min 的性能来算,至多须要 3000 台。
所以这个中央必须要有一些柔性措施把控申请量,寻找一个体验和老本的平衡点。
而这个措施肯定不能通过 logicsvr 拒绝请求来实现,起因是 longpolling 机制下,客户端接管到回包当前是会马上发动一次新申请的。logicsvr 回绝越快,申请量就会越大,越容易造成滚雪球。

图片回到 longpolling 机制,咱们能够发现,失常运行下,recvsvr 没有新音讯时,是能够让申请挂在 proxy 层 hold 住,期待连贯超时或者 longpolling notify 的。
所以,咱们能够利用这个个性,柔性让申请或者回包在 proxy hold 一段时间,来升高申请频率。

如上图所示:

  • ① 依据不同的在线数设定收取距离;
  • ② 客户端上下文里减少字段,记录上一次胜利收取的工夫;
  • ③ 胜利收取后的一个工夫距离内,申请 hold 在 proxy 层;
  • ④ 依据不同的在线数抛弃 longpolling notify。

依据 400w 在线的压测成果:开启自适应大招时触发 8~10s 档位,申请量比没有大招的预期值升高 58%,无效地管制了大直播间对 logicsvr 的压力。

15、成绩展现

1)撑持多个业务稳固运行:

2)压测 1500w 同时在线:

16、参考文献

[1] https://zhuanlan.zhihu.com/p/77289303
[2] https://www.jianshu.com/p/4748af30d194

17、小结与瞻望

咱们通过形象问题、精准剖析、正当设计实现了 liveroom2.0 的迭代,从性能、可靠性、可扩展性、容灾等方面达到撑持单房间 1500w 同时在线甚至更高在线的规范。
在将来咱们将持续优化,比方实现大房间主动从一般 sect 切换到 vip sect,比方针对房间内集体的重要音讯通道,使聊天室的性能和架构更加弱小。

附录:微信、QQ 团队分享的其它技术材料

《微信朋友圈千亿访问量背地的技术挑战和实际总结》
《微信团队分享:微信挪动端的全文检索多音字问题解决方案》
《微信团队分享:iOS 版微信的高性能通用 key-value 组件技术实际》
《微信团队分享:iOS 版微信是如何避免特殊字符导致的炸群、APP 解体的?》
《微信团队原创分享:iOS 版微信的内存监控零碎技术实际》
《iOS 后盾唤醒实战:微信收款到账语音揭示技术总结》
《微信团队分享:视频图像的超分辨率技术原理和利用场景》
《微信团队分享:微信每日亿次实时音视频聊天背地的技术解密》
《微信团队分享:微信 Android 版小视频编码填过的那些坑》
《微信手机端的本地数据全文检索优化之路》
《企业微信客户端中组织架构数据的同步更新计划优化实战》
《微信团队披露:微信界面卡死超级 bug“15。。。。”的前因后果》
《QQ 18 年:解密 8 亿月活的 QQ 后盾服务接口隔离技术》
《月活 8.89 亿的超级 IM 微信是如何进行 Android 端兼容测试的》
《一篇文章 get 微信开源挪动端数据库组件 WCDB 的所有!》
《微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化》
《微信后盾基于工夫序的海量数据冷热分级架构设计实际》
《微信团队原创分享:Android 版微信的臃肿之困与模块化实际之路》
《微信后盾团队:微信后盾异步音讯队列的优化降级实际分享》
《微信团队原创分享:微信客户端 SQLite 数据库损坏修复实际》
《微信 Mars:微信外部正在应用的网络层封装库,行将开源》
《如约而至:微信自用的挪动端 IM 网络层跨平台组件库 Mars 已正式开源》
《[开源 libco 库:单机千万连贯、撑持微信 8 亿用户的后盾框架基石 [源码下载]](http://www.52im.net/thread-62…》
《微信新一代通信安全解决方案:基于 TLS1.3 的 MMTLS 详解》
《微信团队原创分享:Android 版微信后盾保活实战分享 (过程保活篇)》
《微信团队原创分享:Android 版微信后盾保活实战分享(网络保活篇)》
《[Android 版微信从 300KB 到 30MB 的技术演进(PPT 讲稿) [附件下载]](http://www.52im.net/thread-20…》
《微信团队原创分享:Android 版微信从 300KB 到 30MB 的技术演进》
《微信技术总监谈架构:微信之道——大道至简(演讲全文)》
《[微信技术总监谈架构:微信之道——大道至简(PPT 讲稿) [附件下载]](http://www.52im.net/thread-19…》
《如何解读《微信技术总监谈架构:微信之道——大道至简》》
《[微信海量用户背地的后盾零碎存储架构(视频 +PPT) [附件下载]](http://www.52im.net/thread-18…》
《微信异步化革新实际:8 亿月活、单机千万连贯背地的后盾解决方案》
《[微信朋友圈海量技术之道 PPT [附件下载]](http://www.52im.net/thread-17…》
《微信对网络影响的技术试验及剖析(论文全文)》
《一份微信后盾技术架构的总结性笔记》
《[架构之道:3 个程序员成就微信朋友圈日均 10 亿发布量[有视频]](http://www.52im.net/thread-17…》
《疾速裂变:见证微信弱小后盾架构从 0 到 1 的演进历程(一)》
《疾速裂变:见证微信弱小后盾架构从 0 到 1 的演进历程(二)》
《微信团队原创分享:Android 内存透露监控和优化技巧总结》
《全面总结 iOS 版微信降级 iOS9 遇到的各种“坑”》
《微信团队原创资源混同工具:让你的 APK 立减 1M》
《[微信团队原创 Android 资源混同工具:AndResGuard [有源码]](http://www.52im.net/thread-14…》
《Android 版微信安装包“减肥”实战记录》
《iOS 版微信安装包“减肥”实战记录》
《挪动端 IM 实际:iOS 版微信界面卡顿监测计划》
《微信“红包照片”背地的技术难题》
《挪动端 IM 实际:iOS 版微信小视频性能技术计划实录》
《挪动端 IM 实际:Android 版微信如何大幅晋升交互性能(一)》
《挪动端 IM 实际:Android 版微信如何大幅晋升交互性能(二)》
《挪动端 IM 实际:实现 Android 版微信的智能心跳机制》
《挪动端 IM 实际:WhatsApp、Line、微信的心跳策略剖析》
《挪动端 IM 实际:谷歌音讯推送服务(GCM) 钻研(来自微信)》
《挪动端 IM 实际:iOS 版微信的多设施字体适配计划探讨》
《IPv6 技术详解:基本概念、利用现状、技术实际(上篇)》
《IPv6 技术详解:基本概念、利用现状、技术实际(下篇)》
《微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等》
《腾讯技术分享:微信小程序音视频技术背地的故事》
《微信多媒体团队梁俊斌访谈:聊一聊我所理解的音视频技术》
《腾讯技术分享:微信小程序音视频与 WebRTC 互通的技术思路和实际》
《手把手教你读取 Android 版微信和手 Q 的聊天记录(仅作技术钻研学习)》
《微信技术分享:微信的海量 IM 聊天音讯序列号生成实际(算法原理篇)》
《微信技术分享:微信的海量 IM 聊天音讯序列号生成实际(容灾计划篇)》
《微信团队分享:Kotlin 渐被认可,Android 版微信的技术尝鲜之旅》
《社交软件红包技术解密(二):解密微信摇一摇红包从 0 到 1 的技术演进》
《社交软件红包技术解密(三):微信摇一摇红包雨背地的技术细节》
《社交软件红包技术解密(四):微信红包零碎是如何应答高并发的》
《社交软件红包技术解密(五):微信红包零碎是如何实现高可用性的》
《社交软件红包技术解密(六):微信红包零碎的存储层架构演进实际》
《社交软件红包技术解密(十一):解密微信红包随机算法(含代码实现)》
《微信团队分享:极致优化,iOS 版微信编译速度 3 倍晋升的实际总结》
《IM“扫一扫”性能很好做?看看微信“扫一扫识物”的残缺技术实现》
《微信团队分享:微信领取代码重构带来的挪动端软件架构上的思考》
《IM 开发宝典:史上最全,微信各种性能参数和逻辑规定材料汇总》
《微信团队分享:微信直播聊天室单房间 1500 万在线的音讯架构演进之路》

更多同类文章 ……

本文已同步公布于“即时通讯技术圈”公众号。

▲ 本文在公众号上的链接是:点此进入。同步公布链接是:http://www.52im.net/thread-3376-1-1.html

退出移动版