点个重视跟腾讯工程师学技能

周末小技 | 开发一个Feeds流系统——写扩散模式

导语 | 本文首要针对Feeds流进行介绍,将从Feeds流的演变下手,带你一步步了解Feeds流,然后学习怎样从开发视点下手,对其进行建模,笼统出Feeds流常见的架构,最终建立高可用、高扩展、高功用的Feeds流运用。

周末小技 | 开发一个Feeds流系统——写扩散模式

了解Feeds流

在学习怎样开发Feeds流运用前,咱们需求先了解什么是Feeds流。

一、什么是Feeds流

Feeds流是一个继续更新并展现给用户的信息流。它将用户自动订阅的若干音讯源组合在一同构成内容聚合器,协助用户继续地获取最新的订阅源内容。所以它通常具有千人千面的个性化特色。举例来说,咱们在各类手机App中能看到的猜你喜爱,你的重视和老友动态等功用,都是Feeds流的一种表现办法。某种意义上来说,你能够一直向下滑动,然后获取到信息的运用,都是属于Feeds流。

二、为什么会有Feeds流

了解了什么是Feeds流后,咱们能够从产品视点考虑一下,为什么会有Feeds流。

咱们能够和传统的信息获取途径,电视,报纸,杂志进行对比。曾经咱们获取的信息,通常是自动前往某个信息聚合的途径,如:电视的新闻台,去买一份报纸,订货一本杂志。然后,咱们从中许多阅览,然后才干获取到咱们感爱好的信息。上述流程咱们能够知道,咱们想要获取丰厚的信息可不简单。

所以,这就有了Feeds流的呈现了,它的首要作用是:信息聚合。也便是它能够根据你的行为去聚合你想要的信息,然后再将它们以轻松易得的办法提供给你。这个办法便是信息流的办法,你只需求不断的滑动,就能够再各种信息中络绎,而不需求自己去寻找,被动接纳信息。当然,仅仅是流的办法还不以让它成为现今主流的新闻媒体传播途径。因为传统的电视节目,当你不感爱好的时分,你也能够换台进行切换,也是一种简单易得,可自由挑选的办法。Feeds最中心的才能在于聚合。他会根据你的行为聚合出你想要的信息,例如:微博是经过你的重视列表了解你或许想要的信息源,然后以时刻轴的办法聚合各种信息推给你。后来又呈现了抖音的猜你喜爱,它不需求你的手动重视,而是根据你的阅览时长,点赞等信息生成你的用户画像,然后聚合你或许感爱好的信息。朋友圈的Feeds流则是根据你的老友联系,然后聚合了你或许想要的信息。

正是有了这种丰厚多彩的信息聚合才能,用户在运用Feeds流获取信息的时分,就简单取得他们感爱好的内容。然后有一个很好的运用体会。

三、Feeds流的分类

上面提到了几种Feeds流的运用场景,有:微信朋友圈,微博的重视页,抖音的引荐页。这几个例子其实信息聚合的视点都不相同,为此,咱们能够对Feeds流进行分类,了解不同类型的Feeds流,才知道开发过程中,怎样针对不同的运用场景,去规划最合适的架构,完结Feeds流功用。

周末小技 | 开发一个Feeds流系统——写扩散模式

首要,咱们能够从Feeds流的信息源聚合根据进行分类,联系有三种:

从上图咱们能够知道,抖音引荐页能够从你的操作行为中生成你的用户画像,再去匹配聚合信息。而微博则是单向依靠联系,即:我重视了某个大v,就能够获取他发布的信息。这儿的信息聚合根据是单向的重视联系。而微信朋友圈则是双向联系,需求两个人相互经过老友,才会聚合对方的信息到自己的朋友圈中。

三种聚合逻辑,别离适用于信息勘探,信息订阅和熟人交际场景中,各有各的长处。

而除了从信息源聚合根据出发进行分类以外,也能够从Feed流本身的展现逻辑出发进行分类,联系有两类:

周末小技 | 开发一个Feeds流系统——写扩散模式

留意:微博热榜许多人也算成了Feeds流,可是严格意义上来说,他是一个信息流。一切人看到的热榜数据都是相同的,这缺失了信息聚合的特征。所以,本质上热榜的底层模型应该是排行榜,而非feeds流。这儿不将它归为一类。

两个分类是从两个维度对Feeds流进行的区分,可是,不论是什么维度的分类,都是为了更好的贴近业务特色,进行建模开发。

| 信息源挑选根据\排序根据

| 权重引荐 | 时刻次序 | | :– | :– | :– | | 无需依靠联系(无强依靠联系) | 抖音引荐页 | – | | 单向依靠联系(重视) | – | 微博重视页 | | 双向依靠联系(老友) | – | 微信朋友圈 |

实践上,上述表格又能够进一步总结为两类:

分类 运用场景
根据隐含爱好引荐信息,按权重排序展现的feeds流 抖音引荐页
根据用户联系拉取信息,按时刻次序展现的feeds流 微博重视页、微信朋友圈

四、了解Feeds流的前世此生

经过上面的介绍,想必你对Feeds流现已有了必定的了解。那么再说一下它的前身。

Feeds流其实不是一开始便是这种办法。它起源于RSS体系。RSS 翻译过来便是简易信息聚合,它将用户自动订阅的若干音讯源组合在一同构成内容(aggregator),协助用户继续地获取最新的订阅源内容。对用户而言,聚合器是专门用来订阅网站的软件,一般称为 RSS 阅览器、Feed 阅览器等。用户挑选订阅多个订阅源,网站提供 Feed 网址 ,用户将 Feed 网址挂号到聚合器里,在聚合器里构成聚合页,用户便能继续地获取最新的订阅源内容。整个交互流程简而言之是:用户自动订阅感爱好的多个订阅源,订阅器帮用户及时更新订阅源信息,然后按照 timeline 时刻次序展现出来。这样,用户能够经过订阅器获取即时信息,而不用每天都检查各个订阅源是否有更新。

能够看出,上述办法很像是在订货杂志,杂志一旦更新,就会寄到家中。可是那时分的的Rss体系,能订阅的仅仅新闻网站以及博客。直到后来,Facebook 宣布了一项新的主页办法「News Feed」,这一办法打破了传统 RSS 的订阅办法。News Feed 能够看做一个新型聚合器:订阅源由某个新闻网站变成了生产内容的人或许团体,而内容由网站输出的公告新闻,变成了老友(重视对象)的动态(发布的内容以及其他的交际行为)。这样一来,内容丰厚程度直线提高,内容发布者和订阅者也由:人和网站变成了人和人,交际距离大大拉近。很快,这种信息获取形式就遍及起来了。从此今后,RSS 被逼淡出历史舞台。

五、Feeds流模型中的术语

称号 阐明 补白
Feed Feed流中的每一条状况或许音讯都是Feed,比方朋友圈中的一个状况便是一个Feed,微博中的一条微博便是一个Feed。
Feeds流 Feed流本质上是数据流,中心逻辑是服务端体系将 “多个发布者的信息内容” 经过 “重视收藏屏蔽等联系” 推送给 “多个接纳者”。常见的,比方微博上的超话,新版别的微信大众号订阅音讯,抖音里的视频流等等 三大特色:少部分人发布;根据订阅行为关联联系;大多数人读取信息
Timeline Timeline其实是一种Feed流的类型,微博,朋友圈都是Timeline类型的Feed流,可是因为Timeline类型呈现最早,运用最广泛,最为人熟知,有时分也用Timeline来表明Feed流。 又叫时刻轴
重视页Timeline 展现其他人Feed音讯的页面,比方朋友圈,微博的主页等。 又叫做收件箱,每个用户能看到的音讯都会被存储到收件箱中
个人页Timeline 展现自己发送过的Feed音讯的页面,比方微信中的相册,微博的个人页等 又叫做发件箱,自己发布的音讯都会被记载到自己的发件箱中。他人的收件箱内的音讯,也是从他的各个重视人的发件箱内同步过来的。
写分散 一种音讯同步办法,用户发布音讯后,音讯被记载到用户的发件箱中,此刻立刻将发件箱内的音讯同步给一切用户。 又叫做推形式
读分散 一种音讯同步办法,用户发布音讯后,音讯被记载到用户的发件箱中。而音讯的接纳方此刻没有收到音讯。等到音讯接纳方需求检查收件箱的时分,才会去接纳方重视的一切重视人发件箱中拉取音讯,完结音讯同步。 又叫做拉形式

周末小技 | 开发一个Feeds流系统——写扩散模式

了解Feeds流模型的架构

经过上面的介绍,想必你关于即将开发的Feeds流是什么现已满意了解了。那么,接下来咱们从开发的视点切入,再次学习Feeds流。

咱们现已知道了Feeds流能够分为两大类:根据爱好引荐,和根据用户联系拉取。两种形式的Feeds流底层的原理差别很大,所以要别离进行介绍。先介绍第一种:根据用户联系拉取的Feeds流。

一、依靠用户联系的时刻次序Feeds流

第一类Feeds流是依靠用户联系的,按时刻次序进行整合展现的Feeds流。在开发这个模型前,咱们需求先了解这个模型首要面对的挑战在哪儿。

  • Feeds流模型面临的挑战

1.Feed是一种实时音讯,因为音讯是实时发生,实时消费,实时推送的,因而满意实时性是要害。(功用要求高)

2.音讯来自于许多不同的音讯源,音讯的发生属于海量等级。(存储要求大)

3.功用考虑:从音讯发生到音讯消费发生巨大的读写比。(读写失衡模型,时刻排序)

4.音讯发布出去后,要求用户能够感知,最少满意最终一致性,不能够呈现音讯丢掉。(原子性)

  • Feeds流模型需求的基本功用

了解了Feeds流的面对的挑战后,咱们先不着急去处理问题,而是进入详细的功用中去剖析Feeds流模型需求开发的功用。包含如下:

1.用户发布音讯:用户能够发布一条音讯,他的订阅者都能感知到他发布了音讯;(不仅是音讯保证推送出去,而且要有红点提示)

2.用户删去发布的音讯:用户能够删去一条现已发布的音讯,他的订阅者都能实时感知到这条音讯被删去了;

3.用户检查自己发布的音讯:用户检查自己现已发布的一切音讯;

4.用户订阅音讯源:用户能够订阅感爱好的人,重视的博主今后发送的音讯都能够在用户的feeds流中检查到。需求留意的是,有的场景中要求用户Feeds流中能看到博主在被重视之前发的音讯,这就要求订阅的时分,还要自动同步一份博主的一切音讯到用户的Feeds流中。

5.用户撤销音讯源订阅:用户能够撤销现已订阅的人,取关后,Feeds流中关于他的一切音讯要除去。

6.用户检查订阅的音讯流(Feeds流):用户能够以timeline的办法检查一切订阅的音讯源发布的音讯。音讯的删去和更新,都会实时被用户感知到。Feeds流的翻页问题:用户翻页Feeds流的时分,不论Feeds流更新了多少内容,此刻都是沿着最后一次看到的信息往下看。Feeds流前面的信息被修正不予理会。

7.额定功用:音讯支撑装备是非名单,进行细粒度可见权限操控。‘=

8.可扩展功用:信息能够支撑被评论,评论本身也有增修正查

  • 面临问题和解决计划

了解了上述Feeds流需求开发的基本功用,咱们进一步对功用完结中或许遇到的问题进行剖析,而且给出处理计划:

1.发布者发布音讯后,订阅者怎样读取音讯?

这儿一般有三种计划:读分散,写分散和读写结合。

  • 读分散:订阅者读取最新收件箱音讯的时分,订阅者自动去查询重视的人的发件箱,遍历一切的人,获取一切的音讯,然后更新到自己的收件箱中。

  • 写分散:发布者发布音讯后,立刻将自己的音讯同步给他一切的粉丝的收件箱中。

  • 读写结合:因为Feeds流是读多写少的场景,所以一般状况下,咱们选用写分散,体系的功用会比读分散要好。可是,当有大v发布者呈现时,他每次发布音讯,或许音讯需求同步给1亿用户,这样写分散的功用会被严峻影响到。所以,在大v用户上,选用读写结合的办法进行处理。详细来说便是:大v用户发布音讯,音讯写分散到活泼用户收件箱。而不活泼用户在登录的时分,会去自动拉取大v用户的发件箱,完结自身收件箱的更新。

因为Feeds流模型是一种读多写少的场景,所以一般选用写分散更好。

当呈现大v的时分,写分散也太慢了,则选用冷热别离计划。热粉丝则写分散同步,冷粉丝(僵尸粉)则读分散。冷热粉丝能够记载登录次数,时长进行分类。也能够选用session池计划,判别在线的粉丝才进行写分散。

2.Feeds流是怎样翻页的?

Feed流的分页入参不会运用page_size和page_num,而是运用last_id来记载上一页最后一条内容的id。前端读取下一页的时分,必须将last_id作为入参,后台直接找到last_id对应数据,再往后偏移page_size条数据,回来给前端,这样就防止了错位问题。留意:选用该last_id办法要求数据不能被删去,不然前端持有这个id,就又或许找不到对应的记载。为此,删去都选用标志位表明删去。当拉出的数据存在删去的时分,进行再次查询补充。

Feeds流是一个动态列表,每时每刻都或许在更新,所以传统的运用page_size和page_num来分页就不能满意运用了。因为凡是两页之间呈现内容的增加或删去,都会导致错位问题。

写分散下的翻页:因为用户收件箱是提前排序准备好的,所以last_id直接往后读取即可。

读分散下的翻页:因为读分散下,用户的收件箱是实时计算出来的,他翻页的时分,需求去一切重视人的发件箱中拉取必定量的数据。拉取后,需求记载当时拉取到了写信箱的write_last_id1,多少个重视就要记载了多少个write_last_id。然后翻页的时分,需求用这些write_last_id往后拉取新的必定量(比方page_size个)的数据。再用这些数据组成的新收件箱列表,挑选page_size条回来前端。一起,还需求更新他实践拉取了音讯的写信箱中的write_last_id,而且存储。当下一次翻页的时分,这批write_last_id将作为下次的翻页时定位的根据。

对比下来看得出:读分散的翻页比写分散复杂许多。

3.写分散形式下,用户发布音讯能够渐渐分散出去,可是删去,修正都要分散出去,速度过慢会呈现时效性问题。而且,假如真的是删去了数据,或许会影响Feeds流的分页功用(第二点现已介绍)。这种状况怎样处理?

  • 选用软删去+懒删去机制

软删去是指:音讯内容不进行实践删去,而是将音讯置为删去状况即可,不分散出去。如此一来,用户在自己的读取收件箱中音讯的时分,是先获取了音讯Id后,再去数据库查出音讯内容,然后判别状况进行过滤,把现已删去的状况除掉,不回来给前端。此刻也需求从头进行捞数据,填充分页内容。懒删去是指:假如过滤了某个音讯,此刻才把音讯从用户收件箱中真实删去。(redis的zset中的对应id进行除掉,完结Feeds流表的改写)

  • 软删去和懒删去的详细完结如下:选用读分散回查计划。

本次需求,咱们的写分散只写了一个音讯id到用户的收件箱中,所以,用户查询收件箱信息的时分,要进行一个回查将信息丰厚(该计划相比直接把内容一同写入收件箱内会更加节约内存,削减冗余数据,一起音讯删去无需分散)。

4.用户的收件箱改写机遇问题:用户收件箱是音讯同步库,缓存的仅仅音讯id而已,所以能够全量存储一切的重视人发布信息的id。可是,音讯同步库内的音讯实践上变化很大,假如全部选用写分散办法,则会导致实时性问题很大。所以对不同的触发改写操作,咱们需求进行不同处理,各操作如下:

  • 重视他人时,用户的收件箱是否需求触发改写:当用户重视了另一个用户后,他的收件箱需求获取到重视用户的发件箱内一切音讯,然后改写自己的收件箱。(写分散)

  • 撤销重视他人时,用户的收件箱怎样改写:这儿能够选用过滤的办法:咱们从收件箱中获取到了音讯id,然后需求进行回查,可是回查前,判别该id的所属发送人是否还在自己重视列表中。不在则进行除掉音讯,一起删去收件箱中的该音讯id。(读分散+懒删去)

  • 重视人删去或许修正自己音讯时,用户的收件箱怎样改写:这儿也能够选用回查的办法:因为咱们收件箱只存储id,音讯内容需求回查发件人发件箱的详细音讯,所以,回查的时分能够获取最新音讯以此完结删去、修正的同步。

  • 总结:收件箱改写有两类,一类是增加,增加都选用写分散;一类是删去和修正,删去、修正都选用读分散。

上述便是咱们Feeds流模型会遇到的问题,现已给出的一个解决计划。当然,不同的业务场景会遇到不同的侧重点,上述计划仅仅是一个参阅。

周末小技 | 开发一个Feeds流系统——写扩散模式

整体规划

一、架构规划

上面咱们Feeds流的底层模型进行了详细的剖析,归纳考虑后,本次开发决议选用以下架构进行开发体系。

周末小技 | 开发一个Feeds流系统——写扩散模式

上图能够看出是一个音讯发布的流程交互,经过经过的节点看出咱们体系的一个架构。虽然前文讨论了许多问题,但其实底层落到DB便是几个表,每个表进行杰出的规划后,就能够满意咱们的基础的功用要求了。然后是咱们的体系内部,中心难点是发布和拉取Feeds流两个功用。对这些问题,下面咱们也会详细分点介绍规划。

  • 数据结构规划

数据结构规划阐明:本次体系以面向对象思维进行开发,对Feeds流中需求的功用进行笼统,笼统了以下数据结构(简略版别):

1.音讯:

特点:音讯标题,音讯内容,音讯附件,音讯类型,音讯途径

办法:丰厚音讯内容

2.音讯发布处理器:

特点:发送用户,发布装备,音讯id

办法:获取音讯id,获取接受者,获取发布装备,同步音讯,保存音讯

3.用户(音讯拉取器):

特点:用户uid,用户当时操作,用户当时页面途径

办法:获取重视列表,获取粉丝列表,查询发件箱,查询收件箱(收件箱过滤,包含是非名单,软删去等)

4.发布装备:

特点:发布途径,发布办法

办法:获取发布办法,获取发布途径

上述笼统类的类图参阅示意图(非完整版)

周末小技 | 开发一个Feeds流系统——写扩散模式

二、存储和缓存规划

完结音讯推送逻辑,需求将信息进行存储,下面是存储表的规划:

1.音讯表(音讯发布表):

字段称号 字段阐明 补白
msg_id 音讯id
oper_type 操作类型 一般的feeds流体系能够没有这个字段,该字段是和下面的发布装备表结合,用作后续扩展为音讯推送体系的时分用的
msg_title 音讯标题
msg_content 音讯内容 存储json
msg_type 音讯类型:文字,视频等 用于扩展
msg_status 音讯状况:用于符号软删去 用于扩展
msg_channel 音讯所属途径 用于扩展,将来能够接入多个体系
extra_info 额定信息 存储json,用于扩展
sender_id 发布者
ctime 发布时刻
utime 修正时刻
uuid 修正人

2.收件箱:选用redis的zset进行存储,key是“接纳者uid+channelid”,value为“值:发件人uid+音讯id,score:发布时刻戳” 。这样规划,能够将计算下沉,每次收件箱呈现音讯的改写的时分,都会自行排序。下面的redis的zset的图示:

周末小技 | 开发一个Feeds流系统——写扩散模式

3.发布装备表(一般的feeds流能够不考虑这个,我这是后期计划扩展做成音讯推送体系,这儿也能够提供给我们参阅。):

字段称号 字段阐明 补白
send_id 发布id
send_type 发布类型:立即发布,守时发布,周期发布
send_crontab 发布规则 守时发布的时分存储crontab
send_msg_channel 发布途径,如邮件,短信,站内信等 指定推送音讯的途径
channel 装备所属途径 用于扩展,将来能够接入多个体系
send_rule 发布规则:确定在什么操作的时分,会触发发布 如:经过审核的时分,会推送音讯;或许装备发布活动时,会触发推送
extra_info 额定信息 存储json,用于扩展
cuid 创立者
ctime 创立时刻
utime 修正时刻
uuid 修正人

4.重视联系表:

字段称号 字段阐明 补白
main_uid 博主uid
follower_uid 粉丝uid
status 两者状况,首要记载是否拉黑联系 扩展预留
hot_follower 该粉丝是否是热数据 当对大v选用冷热别离的时分,热粉丝假如单独存储,需求进行粉丝和热用户的大规模取交集。所以将每个人的粉丝联系进行符号,查询热数据的时分就能够防止取交集。粉丝冷热状况改变选用写分散即可
extra_info 额定信息 存储json,用于扩展
cuid 创立者
ctime 创立时刻
utime 修正时刻
uuid 修正人

三、中心业务流程

  • 发布Feed流程

当你发布一条Feed音讯的时分,流程是这样的:

1.Feed音讯先进入一个队列服务。

2.先从重视列表中读取到自己的粉丝列表,以及判别自己是否是大V。

3.将自己的Feed音讯写入个人页Timeline(发件箱)。

4.假如是大V,此刻拉取活泼用户;假如是普通用户,则拉取自己的一切粉丝用户。然后将自己的Feed音讯同步写给自己的粉丝,同步的内容为Feed ID。

5.发布Feed的流程到此完毕。

  • 读取Feed流流程

当改写自己的Feed流的时分,流程是这样的:

1.判别自己是否是活泼用户,假如不是,去读取自己重视的大V列表。

2.去读取自己的收件箱,规模开始方位是上次读取到的最新Feed的ID,完毕方位能够使当时时刻,也能够是MAX。然后经过查询出来的FeesId反查Feeds内容,而且把现已软删去的数据除掉出去。

3.假如有拉取到重视的大V列表,则再次并发读取每一个大V的发件箱,假如重视了10个大V,那么则需求10次拜访。

4.兼并2和3步的结果,然后按时刻排序,回来给用户。

至此,运用推拉结合,冷热别离办法的Feeds流发布,读取Feeds流的流程都完毕了。

中心的发布Feed、拉取Feeds流的整体交互图如下:

周末小技 | 开发一个Feeds流系统——写扩散模式

总结

相信看了本文今后,关于怎样完结一个较为牢靠,功用相对有保证的Feeds流体系,你现已有了必定的了解。那么,本次Feeds流的小结到此为止。

粉丝福利,后台回复“Feeds”取得本篇作者引荐相关学习材料

腾讯工程师技能干货直达:

1.超强总结!GPU 烘托管线和硬件架构

2.从鹅厂实例出发!剖析Go Channel底层原理

3.快收藏!最全GO语言完结规划形式【下】

4.怎样成为优秀工程师之软技能篇

阅览原文