关于即时通讯:IM开发技术学习揭秘微信朋友圈这种信息推流背后的系统设计

58次阅读

共计 7558 个字符,预计需要花费 19 分钟才能阅读完成。

本文由徐宁发表于腾讯大讲堂,原题“程序员如何把你关注的内容推送到你眼前?揭秘信息流举荐背地的零碎设计”,有改变和订正。

1、引言

信息推流(以下简称“Feed 流”)这种性能在咱们手机 APP 中简直无处不在(尤其是社交 / 社群产品中),最罕用的就是微信朋友圈、新浪微博等。

对 Feed 流的定义,能够简略了解为只有大拇指不停地往下划手机屏幕,就有一条条的信息不断涌现进去。就像给家畜喂饲料一样,只有它吃光了就要一直再往里加,故此得名 Feed(豢养)。

大多数带有 Feed 流性能的产品都蕴含两种 Feed 流:

  • 1)一种是基于算法:即动静算法举荐,比方今日头条、抖音短视频;
  • 2)一种是基于关注:即社交 / 好友关系,比方微信、知乎。

例如下图中的微博和知乎,顶栏的页卡都蕴含“关注”和“举荐”这两种:

如上图中这两种 Feed 流,它们背地用到的技术差异会比拟大。不同于“举荐”页卡那种千人千面算法举荐的形式,通常“关注”页卡所展现的内容先后顺序都有固定的规定,最常见的规定是基于工夫线来排序,也就是展现“我关注的人所发的帖子、动静、情绪,依据公布工夫从晚到早顺次排列”。

本文将重点探讨的是“关注”性能对应的技术实现:先总结罕用的基于工夫线 Feed 流的后盾技术实现计划,再联合具体的业务场景,依据理论需要在根本设计思路上做一些灵便的使用。

学习交换:

  • 即时通讯 / 推送技术开发交换 5 群:215477170 [举荐]
  • 挪动端 IM 开发入门文章:《新手入门一篇就够:从零开发挪动端 IM》
  • 开源 IM 框架源码:https://github.com/JackJiang2…

(本文同步公布于:http://www.52im.net/thread-36…)

2、本文作者

徐宁:腾讯利用开发工程师,腾讯学院讲师,毕业于上海交通大学。目前负责腾讯智慧批发业务的后端开发工作,有丰盛的视频直播,自动化营销零碎开发教训。

3、Feed 流技术实现计划 1:读扩散

读扩散也称为“拉模式”,这应该是最合乎咱们认知直觉的一种技术实现形式。

原理如下图:

如上图所示:每一个内容发布者都有一个本人的发件箱(“我公布的内容”),每当咱们收回一个新帖子,都存入本人的发件箱中。当咱们的粉丝来浏览时,零碎首先须要拿到粉丝关注的所有人,而后遍历所有发布者的发件箱,取出他们所公布的帖子,而后根据公布工夫排序,展现给阅读者。

这种设计:阅读者读一次 Feed 流,后盾会扩散为 N 次读操作(N 等于关注的人数)以及一次聚合操作,因而称为读扩散。每次读 Feed 流相当于去关注者的收件箱被动拉取帖子,因而也得名——拉模式。

这种模式:

  • 1)益处是:底层存储简略,没有空间节约;
  • 2)害处是:每次读操作会十分重,操作十分多。

构想一下:如果我关注的人数十分多,遍历一遍我所关注的所有人,并且再聚合一下,这个零碎开销会十分大,时延上可能达到无法忍受的境地。

因而:读扩散次要实用零碎中阅读者关注的人没那么多,并且刷 Feed 流并不频繁的场景。

拉模式还有一个比拟大的毛病:就是分页不不便,咱们刷微博或朋友圈,必定是随着大拇指在屏幕一直划动,内容一页一页的从后盾拉取。如果不做其余优化,只采纳实时聚合的形式,下滑到比拟靠后的页码时会十分麻烦。

4、Feed 流技术实现计划 2:写扩散

据统计:大多数 Feed 流产品的读写比大略在 100:1,也就是说大部分状况都是刷 Feed 流看他人发的朋友圈和微博,只有很少状况是本人亲自发一条朋友圈或微博给他人看。

因而:读扩散那种很重的读逻辑并不适宜大多数场景。

咱们宁愿让发帖的过程简单一些,也不愿影响用户读 Feed 流的体验,因而略微革新一下后面计划就有了写扩散。写扩散也称为“推模式”,这种模式会对拉模式的一些毛病做改良。

原理如下图:

如上图所示:零碎中每个用户除了有发件箱,也会有本人的收件箱。当发布者发表一篇帖子的时候,除了往本人发件箱记录一下之外,还会遍历发布者的所有粉丝,往这些粉丝的收件箱也投放一份雷同内容。这样阅读者来读 Feed 流时,间接从本人的收件箱读取即可。

这种设计:每次发表帖子,都会扩散为 M 次写操作(M 等于本人的粉丝数),因而成为写扩散。每篇帖子都会被动推送到所有粉丝的收件箱,因而也得名推模式。

这种模式可想而知:发一篇帖子,背地会波及到很屡次的写操作。通常为了发帖人的用户体验,当公布的帖子写到本人发件箱时,就能够返回公布胜利。后盾另外起一个异步工作,镇定自若地往粉丝收件箱投递帖子即可。

写扩散的益处在于通过数据冗余(一篇帖子会被存储 M 份正本),晋升了阅读者的用户体验。通常适当的数据冗余不是什么问题,然而到了微博明星这里,齐全行不通。比方目前微博粉丝量 Top2 的谢娜与何炅,两个人微博粉丝过亿。

构想一下:如果单纯采纳推模式,那每次谢娜何炅发一条微博,微博后盾都要地震一次。一篇微博导致后台上亿次写操作,这显然是不可行的。

另外:因为写扩散是异步操作,写的太慢会导致帖子收回去半天,有些粉丝仍然没能看见,这种体验也不太好。

通常写扩散实用于好友量不大的状况,比方微信朋友圈正是写扩散模式。每一名微信用户的好友下限为 5000 人,也就是说你发一条朋友圈最多也就扩散到 5000 次写操作,如果异步工作性能好一些,齐全没有问题。

对于微信朋友圈的技术材料:

1)《微信朋友圈海量技术之道 PPT [附件下载]》
2)《微信朋友圈千亿访问量背地的技术挑战和实际总结》
3)《架构之道:3 个程序员成就微信朋友圈日均 10 亿发布量 [有视频]》
5、Feed 流技术实现计划 2:读写混合模式
读写混合也能够称作“推拉联合”,这种形式能够兼具读扩散和写扩散的长处。

咱们首先来总结一下读扩散和写扩散的优缺点:

见上图:认真比拟一下读扩散与写扩散的优缺点,不难发现两者的实用场景是互补的。

因而:在设计后盾存储的时候,咱们如果可能辨别一下场景,在不同场景下抉择最适宜的计划,并且动静调整策略,就实现了读写混合模式。

原理如下图:

以微博为例:当何炅这种粉丝量超大的人发帖时,将帖子写入何炅的发件箱,另外提取进去何炅粉丝当中比拟沉闷的那一批(这曾经能够筛掉大部分了),将何炅的帖子写入他们的收件箱。当一个粉丝量很小的路人甲发帖时,采纳写扩散形式,遍历他的所有粉丝并将帖子写入粉丝收件箱。

对于那些沉闷用户登录刷 Feed 流时:他间接从本人的收件箱读取帖子即可,保障了沉闷用户的体验。

当一个非沉闷的用户忽然登录刷 Feed 流时:

  • 1)一方面须要读他的收件箱;
  • 2)另一面须要遍历他所关注的大 V 用户的发件箱提取帖子,并且做一下聚合展现。

在展现完后:零碎还须要有个工作来判断是否有必要将该用户降级为沉闷用户。

因为有读扩散的场景存在,因而即便是混合模式,每个阅读者所能关注的人数也要设置下限,例如新浪微博限度每个账号最多能够关注 2000 人。

如果不设下限:构想一下有一位用户把微博所有账号全副关注了,那他关上关注列表会读取到微博全站所有帖子,一旦呈现读扩散,零碎必然解体(即便是写扩散,他的收件箱也无奈包容这么多的微博)。

读写混合模式下,零碎须要做两个判断:

  • 1)哪些用户属于大 V,咱们能够将粉丝量作为一个判断指标;
  • 2)哪些用户属于沉闷粉丝,这个判断规范能够是最近一次登录工夫等

这两处判断规范就须要在零碎倒退过程中动静地辨认和调整,没有固定公式了。

能够看出:读写联合模式综合了两种模式的长处,属于最佳计划。

然而他的毛病是:零碎机制非常复杂,给程序员带来有数懊恼。通常在我的项目初期,只有一两个开发人员,用户规模也很小的时候,一步到位地采纳这种混合模式还是要谨慎,容易出 bug。当我的项目规模逐步倒退到新浪微博的程度,有一个大团队专门来做 Feed 流时,读写混合模式才是必须的。

6、Feed 流中的分页问题

下面几节曾经叙述了基于工夫线的几种 Feed 流常见设计方案,但实操起来会比实践要麻烦许多。

接下来专门探讨一个 Feed 流技术计划中的痛点——Feed 流的分页。

不论是读扩散还是写扩散,Feed 流实质上是一个动静列表,列表内容会随着工夫一直变动。传统的前端分页参数应用 page_size 和 page_num,分表示意每页几条,以及以后是第几页。

对于一个动静列表会有如下问题:

如上图所示:在 T1 时刻读取了第一页,T2 时刻有人新发表了“内容 11”,在 T3 时刻如果来拉取第二页,会导致错位呈现,“内容 6”在第一页和第二页都被返回了。事实上,凡是两页之间呈现内容的增加或删除,都会导致错位问题。

为了解决这一问题:通常 Feed 流的分页入参不会应用 page_size 和 page_num,而是应用 last_id 来记录上一页最初一条内容的 id。前端读取下一页的时候,必须将 last_id 作为入参,后盾间接找到 last_id 对应数据,再往后偏移 page_size 条数据,返回给前端,这样就防止了错位问题。

如下图:

采纳 last_id 的计划有一个重要条件:就是 last_id 自身这条数据不能够被硬删除。

构想一下:

  • 1)上图中 T1 时刻返回 5 条数据,last_id 为内容 6;
  • 2)T2 时刻内容 6 被发布者删除;
  • 3)那么 T3 时刻再来申请第二页,咱们基本找不到 last_id 对应的数据了,也就无奈确认分页偏移量。

通常碰到删除的场景:咱们采纳软删除形式,只是在内容上置一个标记位,示意内容已删除。

因为曾经删除的内容不应该再返回给前端,因而软删除模式下,找到 last_id 并往后偏移 page_size 条,如果其中有被删除的数据会导致取得足够的数据条数给前端。

这里一个解决方案是找不够持续再往下找,另一种计划是与前端协商,容许返回条数少于 page_size 条,page_size 只是个倡议值。甚至大家约定好了当前,能够不要 page_size 参数。

7、Feed 流技术计划在某直播利用中的实际

7.1 需要背景
本节将结合实际业务,分享一下理论场景中碰到的一个十分非凡的 Feed 流设计方案。

xx 直播是一款直播带货工具,主播能够创立一场将来时刻的直播,到工夫后开播卖货,直播完结后,主播的粉丝能够查看直播回放。

这样,每个直播场次就有三种状态——预报中(创立一场直播但还未开播)、直播中、回放。

作为观众,我能够关注多位主播,这样从粉丝视角来看,也会有个直播场次的 Feed 流页面。

这个 Feed 流最非凡的中央在于它的排序规定:
](/img/bVcUdJG)

解释一下这个 Feed 流排序规定:

  • 1)我关注的所有主播:正在直播中的场次排在最前;预报中的场次排两头;回放场次排最初;
  • 2)多场次都在直播中的:按开播工夫从晚到早排序;
  • 3)多场次都在预报中的:按预计开播工夫从早到晚排序;
  • 4)多场次都在回放的:按直播完结工夫从晚到早排序。

7.2 问题剖析
本需要最简单的点在于 Feed 流内容融入的“状态”因素,状态的转变会间接导致 Feed 流程序不同。

为了更清晰解释一下对排序的影响,咱们能够用下图具体阐明:

上图中:展现了 4 个主播的 5 个直播场次,作为观众,当我在 T1 时刻关上页面,看到的程序是场次 3 在最上方,其余场次均在预报状态,依照预计开播工夫从早到晚展现。当我在 T2 时刻关上页面,场次 5 在最上方,其余有三场在预报状态排在两头,场次 3 曾经完结了所以排在最初。以此类推,直到所有直播都完结,所有场次最终的状态都会变为回放。

这里须要留神一点:如果我在 T1 时刻关上第一页,而后盯着页面不动,始终盯到 T4 时刻再下划到第二页,这时上一页的 last_id,即分页偏移量很有可能因为直播状态变动而不晓得飞到了什么地位,这会导致重大的错位问题,以及直播状态展现不对立的问题(第一页展现的是 T1 时刻的直播状态,第二页展现的是 T4 时刻的直播状态)。

7.3 解决方案
直播零碎是个单向关系链,和微博有些相似,每个观众会关注大量主播,每个主播会可能有十分多的关注者。

因为有状态变动的存在,写扩散简直无奈实现。

因为:如果采纳写扩散的形式,每次主播创立直播、直播开播、直播完结这三个事件产生时导致的场次状态变动,会扩散为十分屡次的写操作,不仅操作简单,时延上也无奈承受。

微博之所以能够写扩散:就是因为一条微博收回后,这篇微博就不会再有任何影响排序的状态转变。

而在咱们场景中:“预报中”与“直播中”是两个两头态,而“回放”状态才是所有直播的最终归宿,一旦进入回放,这场直播也就不会再有状态转变。因而“直播中”与“预报中”状态能够采纳读扩散形式,“回放”状态采取写扩散形式。

最终的计划如下图所示:

如上图:会影响直播状态的三种事件(创立直播、开播、完结直播)全副采纳监听队列异步解决。

咱们为每一位主播保护一个直播中 + 预报中状态的优先级队列:

1)每当监听到有主播创立直播时,将直播场次退出队列中,得分为开播的工夫戳的相反数(正数);
2)每当监听到有主播开播时,把这场直播在队列中的得分批改为开播工夫(负数);
3)每当监听到有主播完结直播,则异步地将播放信息投递到每个观众的回放队列中。
这里有一个小技巧:前文提到,直播中状态依照开播工夫从大到小排序,而预报中状态则依照开播工夫从小到大排序,因而如果将预报中状态的得分全副取开播工夫相反数,那排序同样就成为了从大到小。这样的转化能够保障直播中与预报中同处于一个队列排序。预报中得分全都为正数,直播中得分全都为负数,最初聚合时能够保障所有直播中全都天然排在预报中后面。

另外:前文还提到的另一个问题是 T1 时刻拉取第一页,T4 时刻拉取第二页,导致第一页和第二页直播间状态不对立。

解决这个问题的方法是通过快照形式:当观众来拉取第一页 Feed 流时,咱们根据以后工夫,将全副直播中和预报中状态的场次建设一份快照,应用一个 session_id 标识,每次前端分页拉取时,咱们间接从快照中读取即可。如果快照中读取结束,证实该观众的直播中和预报中场次全副读完,剩下的则应用回放队列进行补充。

照此一来,咱们的 Feed 流零碎,前端分页拉取的参数一共有 4 个:

每当碰到 session_id 和 last_id 为空,则证实用户想要读取第一页,须要从新构建快照。

这里还有一个衍生问题:session_id 的如何取值?

答案是:

  • 1)如果不思考同一个观众在多端登录的状况,其实每一位观众保护一个快照 id 即可,也就是间接将零碎用户 id 设为 session_id;
  • 2)如果思考多端登录的状况,则 session_id 中必须蕴含每个端的信息,以防止多端快照相互影响;
  • 3)如果不疼爱内存,也能够每次随机一个字符串作为 session_id,并设置一个足够长的过期工夫,让快照天然过期。

以上设计:其实零碎计算量最大的时刻就是拉取第一页,构建快照的开销。

目前的线上数据,对于只关注不到 10 个主播的观众(这也是大多数场景),拉取第一页的 QPS 能够达到 1.5 万。如果将第二页当前的申请也算进来,Feed 流的综合 QPS 能够达到更高水平,撑持目前的用户规模曾经入不敷出。如果咱们拉取第一页时只获取到前 10 条即可间接返回,将构建快照操作改为异步,兴许 QPS 能够更高一些,这可能是后续的优化点。

8、本文小结

简直所有基于工夫线和关注关系的 Feed 流都逃不开三种根本设计模式:

  • 1)读扩散;
  • 2)写扩散;
  • 3)读写混合。

具体到理论业务中,可能会有更简单的场景,比方本文所说的:

  • 1)状态流转影响排序;
  • 2)微博朋友圈场景中会有广告接入、特地关注、热点话题等可能影响到 Feed 流排序的因素。

这些场景就只能依据业务需要,做绝对应的变通了。

附录:更多社交利用架构设计文章

《浅谈 IM 零碎的架构设计》
《简述挪动端 IM 开发的那些坑:架构设计、通信协议和客户端》
《一套海量在线用户的挪动端 IM 架构设计实际分享 (含具体图文)》
《一套原创分布式即时通讯(IM) 零碎实践架构计划》
《从零到卓越:京东客服即时通讯零碎的技术架构演进历程》
《蘑菇街即时通讯 /IM 服务器开发之架构抉择》
《腾讯 QQ1.4 亿在线用户的技术挑战和架构演进之路 PPT》
《微信后盾基于工夫序的海量数据冷热分级架构设计实际》
《微信技术总监谈架构:微信之道——大道至简(演讲全文)》
《如何解读《微信技术总监谈架构:微信之道——大道至简》》
《疾速裂变:见证微信弱小后盾架构从 0 到 1 的演进历程(一)》
《挪动端 IM 中大规模群音讯的推送如何保障效率、实时性?》
《古代 IM 零碎中聊天音讯的同步和存储计划探讨》
《微信朋友圈千亿访问量背地的技术挑战和实际总结》
《以微博类利用场景为例,总结海量社交零碎的架构设计步骤》
《子弹短信光鲜的背地:网易云信首席架构师分享亿级 IM 平台的技术实际》
《知乎技术分享:从单机到 2000 万 QPS 并发的 Redis 高性能缓存实际之路》
《微信技术分享:微信的海量 IM 聊天音讯序列号生成实际(算法原理篇)》
《微信技术分享:微信的海量 IM 聊天音讯序列号生成实际(容灾计划篇)》
《一套高可用、易伸缩、高并发的 IM 群聊、单聊架构方案设计实际》
《社交软件红包技术解密(一):全面解密 QQ 红包技术计划——架构、技术实现等》
《社交软件红包技术解密(二):解密微信摇一摇红包从 0 到 1 的技术演进》
《社交软件红包技术解密(三):微信摇一摇红包雨背地的技术细节》
《社交软件红包技术解密(四):微信红包零碎是如何应答高并发的》
《社交软件红包技术解密(五):微信红包零碎是如何实现高可用性的》
《社交软件红包技术解密(六):微信红包零碎的存储层架构演进实际》
《社交软件红包技术解密(七):支付宝红包的海量高并发技术实际》
《社交软件红包技术解密(八):全面解密微博红包技术计划》
《社交软件红包技术解密(九):谈谈手 Q 红包的性能逻辑、容灾、运维、架构等》
《从游击队到正规军(一):马蜂窝旅游网的 IM 零碎架构演进之路》
《从游击队到正规军(二):马蜂窝旅游网的 IM 客户端架构演进和实际总结》
《从游击队到正规军(三):基于 Go 的马蜂窝旅游网分布式 IM 零碎技术实际》
《瓜子 IM 智能客服零碎的数据架构设计(整顿自现场演讲,有配套 PPT)》
《阿里钉钉技术分享:企业级 IM 王者——钉钉在后端架构上的过人之处》
《微信后盾基于工夫序的新一代海量数据存储架构的设计实际》
《阿里技术分享:电商 IM 音讯平台,在群聊、直播场景下的技术实际》
《一套亿级用户的 IM 架构技术干货(上篇):整体架构、服务拆分等》
《一套亿级用户的 IM 架构技术干货(下篇):可靠性、有序性、弱网优化等》
《从老手到专家:如何设计一套亿级音讯量的分布式 IM 零碎》
《企业微信的 IM 架构设计揭秘:音讯模型、万人群、已读回执、音讯撤回等》
《融云技术分享:全面揭秘亿级 IM 音讯的牢靠投递机制》
《IM 开发技术学习:揭秘微信朋友圈这种信息推流背地的零碎设计》

更多同类文章 ……

本文已同步公布于“即时通讯技术圈”公众号。
同步公布链接是:http://www.52im.net/thread-36…

正文完
 0