IM開(kāi)發(fā)技術(shù)學(xué)習(xí):揭秘微信朋友圈這種信息推流背后的系統(tǒng)設(shè)計(jì)

本文由徐寧發(fā)表于騰訊大講堂,原題“程序員如何把你關(guān)注的內(nèi)容推送到你眼前?揭秘信息流推薦背后的系統(tǒng)設(shè)計(jì)”,有改動(dòng)和修訂。
1、引言
信息推流(以下簡(jiǎn)稱(chēng)“Feed流”)這種功能在我們手機(jī)APP中幾乎無(wú)處不在(尤其是社交/社群產(chǎn)品中),最常用的就是微信朋友圈、新浪微博等。
對(duì)Feed流的定義,可以簡(jiǎn)單理解為只要大拇指不停地往下劃手機(jī)屏幕,就有一條條的信息不斷涌現(xiàn)出來(lái)。就像給牲畜喂飼料一樣,只要它吃光了就要不斷再往里加,故此得名Feed(飼養(yǎng))。
大多數(shù)帶有Feed流功能的產(chǎn)品都包含兩種Feed流:
1)一種是基于算法:即動(dòng)態(tài)算法推薦,比如今日頭條、抖音短視頻;
2)一種是基于關(guān)注:即社交/好友關(guān)系,比如微信、知乎。
例如下圖中的微博和知乎,頂欄的頁(yè)卡都包含“關(guān)注”和“推薦”這兩種:

如上圖中這兩種Feed流,它們背后用到的技術(shù)差別會(huì)比較大。不同于“推薦”頁(yè)卡那種千人千面算法推薦的方式,通?!瓣P(guān)注”頁(yè)卡所展示的內(nèi)容先后順序都有固定的規(guī)則,最常見(jiàn)的規(guī)則是基于時(shí)間線來(lái)排序,也就是展示“我關(guān)注的人所發(fā)的帖子、動(dòng)態(tài)、心情,根據(jù)發(fā)布時(shí)間從晚到早依次排列”。
本文將重點(diǎn)討論的是“關(guān)注”功能對(duì)應(yīng)的技術(shù)實(shí)現(xiàn):先總結(jié)常用的基于時(shí)間線Feed流的后臺(tái)技術(shù)實(shí)現(xiàn)方案,再結(jié)合具體的業(yè)務(wù)場(chǎng)景,根據(jù)實(shí)際需求在基本設(shè)計(jì)思路上做一些靈活的運(yùn)用。

學(xué)習(xí)交流:
- 即時(shí)通訊/推送技術(shù)開(kāi)發(fā)交流5群:215477170?[推薦]
- 移動(dòng)端IM開(kāi)發(fā)入門(mén)文章:《新手入門(mén)一篇就夠:從零開(kāi)發(fā)移動(dòng)端IM》
- 開(kāi)源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK
(本文同步發(fā)布于:http://www.52im.net/thread-3675-1-1.html)
2、本文作者

徐寧:騰訊應(yīng)用開(kāi)發(fā)工程師,騰訊學(xué)院講師,畢業(yè)于上海交通大學(xué)。目前負(fù)責(zé)騰訊智慧零售業(yè)務(wù)的后端開(kāi)發(fā)工作,有豐富的視頻直播,自動(dòng)化營(yíng)銷(xiāo)系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)。
3、Feed流技術(shù)實(shí)現(xiàn)方案1:讀擴(kuò)散
讀擴(kuò)散也稱(chēng)為“拉模式”,這應(yīng)該是最符合我們認(rèn)知直覺(jué)的一種技術(shù)實(shí)現(xiàn)方式。
原理如下圖:

如上圖所示:每一個(gè)內(nèi)容發(fā)布者都有一個(gè)自己的發(fā)件箱(“我發(fā)布的內(nèi)容”),每當(dāng)我們發(fā)出一個(gè)新帖子,都存入自己的發(fā)件箱中。當(dāng)我們的粉絲來(lái)閱讀時(shí),系統(tǒng)首先需要拿到粉絲關(guān)注的所有人,然后遍歷所有發(fā)布者的發(fā)件箱,取出他們所發(fā)布的帖子,然后依據(jù)發(fā)布時(shí)間排序,展示給閱讀者。
這種設(shè)計(jì):閱讀者讀一次Feed流,后臺(tái)會(huì)擴(kuò)散為N次讀操作(N等于關(guān)注的人數(shù))以及一次聚合操作,因此稱(chēng)為讀擴(kuò)散。每次讀Feed流相當(dāng)于去關(guān)注者的收件箱主動(dòng)拉取帖子,因此也得名——拉模式。
這種模式:
1)好處是:底層存儲(chǔ)簡(jiǎn)單,沒(méi)有空間浪費(fèi);
2)壞處是:每次讀操作會(huì)非常重,操作非常多。
設(shè)想一下:如果我關(guān)注的人數(shù)非常多,遍歷一遍我所關(guān)注的所有人,并且再聚合一下,這個(gè)系統(tǒng)開(kāi)銷(xiāo)會(huì)非常大,時(shí)延上可能達(dá)到無(wú)法忍受的地步。
因此:讀擴(kuò)散主要適用系統(tǒng)中閱讀者關(guān)注的人沒(méi)那么多,并且刷Feed流并不頻繁的場(chǎng)景。
拉模式還有一個(gè)比較大的缺點(diǎn):就是分頁(yè)不方便,我們刷微博或朋友圈,肯定是隨著大拇指在屏幕不斷劃動(dòng),內(nèi)容一頁(yè)一頁(yè)的從后臺(tái)拉取。如果不做其他優(yōu)化,只采用實(shí)時(shí)聚合的方式,下滑到比較靠后的頁(yè)碼時(shí)會(huì)非常麻煩。
4、Feed流技術(shù)實(shí)現(xiàn)方案2:寫(xiě)擴(kuò)散
據(jù)統(tǒng)計(jì):大多數(shù)Feed流產(chǎn)品的讀寫(xiě)比大概在100:1,也就是說(shuō)大部分情況都是刷Feed流看別人發(fā)的朋友圈和微博,只有很少情況是自己親自發(fā)一條朋友圈或微博給別人看。
因此:讀擴(kuò)散那種很重的讀邏輯并不適合大多數(shù)場(chǎng)景。
我們寧愿讓發(fā)帖的過(guò)程復(fù)雜一些,也不愿影響用戶(hù)讀Feed流的體驗(yàn),因此稍微改造一下前面方案就有了寫(xiě)擴(kuò)散。寫(xiě)擴(kuò)散也稱(chēng)為“推模式”,這種模式會(huì)對(duì)拉模式的一些缺點(diǎn)做改進(jìn)。
原理如下圖:

如上圖所示:系統(tǒng)中每個(gè)用戶(hù)除了有發(fā)件箱,也會(huì)有自己的收件箱。當(dāng)發(fā)布者發(fā)表一篇帖子的時(shí)候,除了往自己發(fā)件箱記錄一下之外,還會(huì)遍歷發(fā)布者的所有粉絲,往這些粉絲的收件箱也投放一份相同內(nèi)容。這樣閱讀者來(lái)讀Feed流時(shí),直接從自己的收件箱讀取即可。
這種設(shè)計(jì):每次發(fā)表帖子,都會(huì)擴(kuò)散為M次寫(xiě)操作(M等于自己的粉絲數(shù)),因此成為寫(xiě)擴(kuò)散。每篇帖子都會(huì)主動(dòng)推送到所有粉絲的收件箱,因此也得名推模式。
這種模式可想而知:發(fā)一篇帖子,背后會(huì)涉及到很多次的寫(xiě)操作。通常為了發(fā)帖人的用戶(hù)體驗(yàn),當(dāng)發(fā)布的帖子寫(xiě)到自己發(fā)件箱時(shí),就可以返回發(fā)布成功。后臺(tái)另外起一個(gè)異步任務(wù),不慌不忙地往粉絲收件箱投遞帖子即可。
寫(xiě)擴(kuò)散的好處在于通過(guò)數(shù)據(jù)冗余(一篇帖子會(huì)被存儲(chǔ)M份副本),提升了閱讀者的用戶(hù)體驗(yàn)。通常適當(dāng)?shù)臄?shù)據(jù)冗余不是什么問(wèn)題,但是到了微博明星這里,完全行不通。比如目前微博粉絲量Top2的謝娜與何炅,兩個(gè)人微博粉絲過(guò)億。

設(shè)想一下:如果單純采用推模式,那每次謝娜何炅發(fā)一條微博,微博后臺(tái)都要地震一次。一篇微博導(dǎo)致后臺(tái)上億次寫(xiě)操作,這顯然是不可行的。
另外:由于寫(xiě)擴(kuò)散是異步操作,寫(xiě)的太慢會(huì)導(dǎo)致帖子發(fā)出去半天,有些粉絲依然沒(méi)能看見(jiàn),這種體驗(yàn)也不太好。
通常寫(xiě)擴(kuò)散適用于好友量不大的情況,比如微信朋友圈正是寫(xiě)擴(kuò)散模式。每一名微信用戶(hù)的好友上限為5000人,也就是說(shuō)你發(fā)一條朋友圈最多也就擴(kuò)散到5000次寫(xiě)操作,如果異步任務(wù)性能好一些,完全沒(méi)有問(wèn)題。
關(guān)于微信朋友圈的技術(shù)資料:
1)《微信朋友圈海量技術(shù)之道PPT [附件下載]》
2)《微信朋友圈千億訪問(wèn)量背后的技術(shù)挑戰(zhàn)和實(shí)踐總結(jié)》
3)《架構(gòu)之道:3個(gè)程序員成就微信朋友圈日均10億發(fā)布量[有視頻]》
5、Feed流技術(shù)實(shí)現(xiàn)方案2:讀寫(xiě)混合模式
讀寫(xiě)混合也可以稱(chēng)作“推拉結(jié)合”,這種方式可以兼具讀擴(kuò)散和寫(xiě)擴(kuò)散的優(yōu)點(diǎn)。
我們首先來(lái)總結(jié)一下讀擴(kuò)散和寫(xiě)擴(kuò)散的優(yōu)缺點(diǎn):

見(jiàn)上圖:仔細(xì)比較一下讀擴(kuò)散與寫(xiě)擴(kuò)散的優(yōu)缺點(diǎn),不難發(fā)現(xiàn)兩者的適用場(chǎng)景是互補(bǔ)的。
因此:在設(shè)計(jì)后臺(tái)存儲(chǔ)的時(shí)候,我們?nèi)绻軌騾^(qū)分一下場(chǎng)景,在不同場(chǎng)景下選擇最適合的方案,并且動(dòng)態(tài)調(diào)整策略,就實(shí)現(xiàn)了讀寫(xiě)混合模式。
原理如下圖:

以微博為例:當(dāng)何炅這種粉絲量超大的人發(fā)帖時(shí),將帖子寫(xiě)入何炅的發(fā)件箱,另外提取出來(lái)何炅粉絲當(dāng)中比較活躍的那一批(這已經(jīng)可以篩掉大部分了),將何炅的帖子寫(xiě)入他們的收件箱。當(dāng)一個(gè)粉絲量很小的路人甲發(fā)帖時(shí),采用寫(xiě)擴(kuò)散方式,遍歷他的所有粉絲并將帖子寫(xiě)入粉絲收件箱。
對(duì)于那些活躍用戶(hù)登錄刷Feed流時(shí):他直接從自己的收件箱讀取帖子即可,保證了活躍用戶(hù)的體驗(yàn)。
當(dāng)一個(gè)非活躍的用戶(hù)突然登錄刷Feed流時(shí):
1)一方面需要讀他的收件箱;
2)另一面需要遍歷他所關(guān)注的大V用戶(hù)的發(fā)件箱提取帖子,并且做一下聚合展示。
在展示完后:系統(tǒng)還需要有個(gè)任務(wù)來(lái)判斷是否有必要將該用戶(hù)升級(jí)為活躍用戶(hù)。
因?yàn)橛凶x擴(kuò)散的場(chǎng)景存在,因此即使是混合模式,每個(gè)閱讀者所能關(guān)注的人數(shù)也要設(shè)置上限,例如新浪微博限制每個(gè)賬號(hào)最多可以關(guān)注2000人。
如果不設(shè)上限:設(shè)想一下有一位用戶(hù)把微博所有賬號(hào)全部關(guān)注了,那他打開(kāi)關(guān)注列表會(huì)讀取到微博全站所有帖子,一旦出現(xiàn)讀擴(kuò)散,系統(tǒng)必然崩潰(即使是寫(xiě)擴(kuò)散,他的收件箱也無(wú)法容納這么多的微博)。
讀寫(xiě)混合模式下,系統(tǒng)需要做兩個(gè)判斷:
1)哪些用戶(hù)屬于大V,我們可以將粉絲量作為一個(gè)判斷指標(biāo);
2)哪些用戶(hù)屬于活躍粉絲,這個(gè)判斷標(biāo)準(zhǔn)可以是最近一次登錄時(shí)間等。
這兩處判斷標(biāo)準(zhǔn)就需要在系統(tǒng)發(fā)展過(guò)程中動(dòng)態(tài)地識(shí)別和調(diào)整,沒(méi)有固定公式了。
可以看出:讀寫(xiě)結(jié)合模式綜合了兩種模式的優(yōu)點(diǎn),屬于最佳方案。
然而他的缺點(diǎn)是:系統(tǒng)機(jī)制非常復(fù)雜,給程序員帶來(lái)無(wú)數(shù)煩惱。通常在項(xiàng)目初期,只有一兩個(gè)開(kāi)發(fā)人員,用戶(hù)規(guī)模也很小的時(shí)候,一步到位地采用這種混合模式還是要慎重,容易出bug。當(dāng)項(xiàng)目規(guī)模逐漸發(fā)展到新浪微博的水平,有一個(gè)大團(tuán)隊(duì)專(zhuān)門(mén)來(lái)做Feed流時(shí),讀寫(xiě)混合模式才是必須的。
6、Feed流中的分頁(yè)問(wèn)題
上面幾節(jié)已經(jīng)敘述了基于時(shí)間線的幾種Feed流常見(jiàn)設(shè)計(jì)方案,但實(shí)操起來(lái)會(huì)比理論要麻煩許多。
接下來(lái)專(zhuān)門(mén)討論一個(gè)Feed流技術(shù)方案中的痛點(diǎn)——Feed流的分頁(yè)。
不管是讀擴(kuò)散還是寫(xiě)擴(kuò)散,F(xiàn)eed流本質(zhì)上是一個(gè)動(dòng)態(tài)列表,列表內(nèi)容會(huì)隨著時(shí)間不斷變化。傳統(tǒng)的前端分頁(yè)參數(shù)使用page_size和page_num,分表表示每頁(yè)幾條,以及當(dāng)前是第幾頁(yè)。
對(duì)于一個(gè)動(dòng)態(tài)列表會(huì)有如下問(wèn)題:

如上圖所示:在T1時(shí)刻讀取了第一頁(yè),T2時(shí)刻有人新發(fā)表了“內(nèi)容11”,在T3時(shí)刻如果來(lái)拉取第二頁(yè),會(huì)導(dǎo)致錯(cuò)位出現(xiàn),“內(nèi)容6”在第一頁(yè)和第二頁(yè)都被返回了。事實(shí)上,但凡兩頁(yè)之間出現(xiàn)內(nèi)容的添加或刪除,都會(huì)導(dǎo)致錯(cuò)位問(wèn)題。
為了解決這一問(wèn)題:通常Feed流的分頁(yè)入?yún)⒉粫?huì)使用page_size和page_num,而是使用last_id來(lái)記錄上一頁(yè)最后一條內(nèi)容的id。前端讀取下一頁(yè)的時(shí)候,必須將last_id作為入?yún)?,后臺(tái)直接找到last_id對(duì)應(yīng)數(shù)據(jù),再往后偏移page_size條數(shù)據(jù),返回給前端,這樣就避免了錯(cuò)位問(wèn)題。
如下圖:

采用last_id的方案有一個(gè)重要條件:就是last_id本身這條數(shù)據(jù)不可以被硬刪除。
設(shè)想一下:
1)上圖中T1時(shí)刻返回5條數(shù)據(jù),last_id為內(nèi)容6;
2)T2時(shí)刻內(nèi)容6被發(fā)布者刪除;
3)那么T3時(shí)刻再來(lái)請(qǐng)求第二頁(yè),我們根本找不到last_id對(duì)應(yīng)的數(shù)據(jù)了,也就無(wú)法確認(rèn)分頁(yè)偏移量。
通常碰到刪除的場(chǎng)景:我們采用軟刪除方式,只是在內(nèi)容上置一個(gè)標(biāo)志位,表示內(nèi)容已刪除。
由于已經(jīng)刪除的內(nèi)容不應(yīng)該再返回給前端,因此軟刪除模式下,找到last_id并往后偏移page_size條,如果其中有被刪除的數(shù)據(jù)會(huì)導(dǎo)致獲得足夠的數(shù)據(jù)條數(shù)給前端。
這里一個(gè)解決方案是找不夠繼續(xù)再往下找,另一種方案是與前端協(xié)商,允許返回條數(shù)少于page_size條,page_size只是個(gè)建議值。甚至大家約定好了以后,可以不要page_size參數(shù)。
7、Feed流技術(shù)方案在某直播應(yīng)用中的實(shí)踐
7.1 需求背景
本節(jié)將結(jié)合實(shí)際業(yè)務(wù),分享一下實(shí)際場(chǎng)景中碰到的一個(gè)非常特殊的Feed流設(shè)計(jì)方案。
xx 直播是一款直播帶貨工具,主播可以創(chuàng)建一場(chǎng)未來(lái)時(shí)刻的直播,到時(shí)間后開(kāi)播賣(mài)貨,直播結(jié)束后,主播的粉絲可以查看直播回放。
這樣,每個(gè)直播場(chǎng)次就有三種狀態(tài)——預(yù)告中(創(chuàng)建一場(chǎng)直播但還未開(kāi)播)、直播中、回放。
作為觀眾,我可以關(guān)注多位主播,這樣從粉絲視角來(lái)看,也會(huì)有個(gè)直播場(chǎng)次的Feed流頁(yè)面。
這個(gè)Feed流最特殊的地方在于它的排序規(guī)則:

解釋一下這個(gè)Feed流排序規(guī)則:
1)我關(guān)注的所有主播:正在直播中的場(chǎng)次排在最前;預(yù)告中的場(chǎng)次排中間;回放場(chǎng)次排最后;
2)多場(chǎng)次都在直播中的:按開(kāi)播時(shí)間從晚到早排序;
3)多場(chǎng)次都在預(yù)告中的:按預(yù)計(jì)開(kāi)播時(shí)間從早到晚排序;
4)多場(chǎng)次都在回放的:按直播結(jié)束時(shí)間從晚到早排序。
7.2 問(wèn)題分析
本需求最復(fù)雜的點(diǎn)在于Feed流內(nèi)容融入的“狀態(tài)”因素,狀態(tài)的轉(zhuǎn)變會(huì)直接導(dǎo)致Feed流順序不同。
為了更清晰解釋一下對(duì)排序的影響,我們可以用下圖詳細(xì)說(shuō)明:

上圖中:展示了4個(gè)主播的5個(gè)直播場(chǎng)次,作為觀眾,當(dāng)我在T1時(shí)刻打開(kāi)頁(yè)面,看到的順序是場(chǎng)次3在最上方,其余場(chǎng)次均在預(yù)告狀態(tài),按照預(yù)計(jì)開(kāi)播時(shí)間從早到晚展示。當(dāng)我在T2時(shí)刻打開(kāi)頁(yè)面,場(chǎng)次5在最上方,其余有三場(chǎng)在預(yù)告狀態(tài)排在中間,場(chǎng)次3已經(jīng)結(jié)束了所以排在最后。以此類(lèi)推,直到所有直播都結(jié)束,所有場(chǎng)次最終的狀態(tài)都會(huì)變?yōu)榛胤拧?/p>
這里需要注意一點(diǎn):如果我在T1時(shí)刻打開(kāi)第一頁(yè),然后盯著頁(yè)面不動(dòng),一直盯到T4時(shí)刻再下劃到第二頁(yè),這時(shí)上一頁(yè)的last_id,即分頁(yè)偏移量很有可能因?yàn)橹辈顟B(tài)變化而不知道飛到了什么位置,這會(huì)導(dǎo)致嚴(yán)重的錯(cuò)位問(wèn)題,以及直播狀態(tài)展示不統(tǒng)一的問(wèn)題(第一頁(yè)展示的是T1時(shí)刻的直播狀態(tài),第二頁(yè)展示的是T4時(shí)刻的直播狀態(tài))。
7.3 解決方案
直播系統(tǒng)是個(gè)單向關(guān)系鏈,和微博有些類(lèi)似,每個(gè)觀眾會(huì)關(guān)注少量主播,每個(gè)主播會(huì)可能有非常多的關(guān)注者。
由于有狀態(tài)變化的存在,寫(xiě)擴(kuò)散幾乎無(wú)法實(shí)現(xiàn)。
因?yàn)椋?/strong>如果采用寫(xiě)擴(kuò)散的方式,每次主播創(chuàng)建直播、直播開(kāi)播、直播結(jié)束這三個(gè)事件發(fā)生時(shí)導(dǎo)致的場(chǎng)次狀態(tài)變化,會(huì)擴(kuò)散為非常多次的寫(xiě)操作,不僅操作復(fù)雜,時(shí)延上也無(wú)法接受。
微博之所以可以寫(xiě)擴(kuò)散:就是因?yàn)橐粭l微博發(fā)出后,這篇微博就不會(huì)再有任何影響排序的狀態(tài)轉(zhuǎn)變。
而在我們場(chǎng)景中:“預(yù)告中”與“直播中”是兩個(gè)中間態(tài),而“回放”狀態(tài)才是所有直播的最終歸宿,一旦進(jìn)入回放,這場(chǎng)直播也就不會(huì)再有狀態(tài)轉(zhuǎn)變。因此“直播中”與“預(yù)告中”狀態(tài)可以采用讀擴(kuò)散方式,“回放”狀態(tài)采取寫(xiě)擴(kuò)散方式。
最終的方案如下圖所示:

如上圖:會(huì)影響直播狀態(tài)的三種事件(創(chuàng)建直播、開(kāi)播、結(jié)束直播)全部采用監(jiān)聽(tīng)隊(duì)列異步處理。
我們?yōu)槊恳晃恢鞑ゾS護(hù)一個(gè)直播中+預(yù)告中狀態(tài)的優(yōu)先級(jí)隊(duì)列:
1)每當(dāng)監(jiān)聽(tīng)到有主播創(chuàng)建直播時(shí),將直播場(chǎng)次加入隊(duì)列中,得分為開(kāi)播的時(shí)間戳的相反數(shù)(負(fù)數(shù));
2)每當(dāng)監(jiān)聽(tīng)到有主播開(kāi)播時(shí),把這場(chǎng)直播在隊(duì)列中的得分修改為開(kāi)播時(shí)間(正數(shù));
3)每當(dāng)監(jiān)聽(tīng)到有主播結(jié)束直播,則異步地將播放信息投遞到每個(gè)觀眾的回放隊(duì)列中。
這里有一個(gè)小技巧:前文提到,直播中狀態(tài)按照開(kāi)播時(shí)間從大到小排序,而預(yù)告中狀態(tài)則按照開(kāi)播時(shí)間從小到大排序,因此如果將預(yù)告中狀態(tài)的得分全部取開(kāi)播時(shí)間相反數(shù),那排序同樣就成為了從大到小。這樣的轉(zhuǎn)化可以保證直播中與預(yù)告中同處于一個(gè)隊(duì)列排序。預(yù)告中得分全都為負(fù)數(shù),直播中得分全都為正數(shù),最后聚合時(shí)可以保證所有直播中全都自然排在預(yù)告中前面。
另外:前文還提到的另一個(gè)問(wèn)題是T1時(shí)刻拉取第一頁(yè),T4時(shí)刻拉取第二頁(yè),導(dǎo)致第一頁(yè)和第二頁(yè)直播間狀態(tài)不統(tǒng)一。
解決這個(gè)問(wèn)題的辦法是通過(guò)快照方式:當(dāng)觀眾來(lái)拉取第一頁(yè)Feed流時(shí),我們依據(jù)當(dāng)前時(shí)間,將全部直播中和預(yù)告中狀態(tài)的場(chǎng)次建立一份快照,使用一個(gè)session_id標(biāo)識(shí),每次前端分頁(yè)拉取時(shí),我們直接從快照中讀取即可。如果快照中讀取完畢,證明該觀眾的直播中和預(yù)告中場(chǎng)次全部讀完,剩下的則使用回放隊(duì)列進(jìn)行補(bǔ)充。
照此一來(lái),我們的Feed流系統(tǒng),前端分頁(yè)拉取的參數(shù)一共有4個(gè):

每當(dāng)碰到session_id和last_id為空,則證明用戶(hù)想要讀取第一頁(yè),需要重新構(gòu)建快照。
這里還有一個(gè)衍生問(wèn)題:session_id的如何取值?
答案是:
1)如果不考慮同一個(gè)觀眾在多端登錄的情況,其實(shí)每一位觀眾維護(hù)一個(gè)快照id即可,也就是直接將系統(tǒng)用戶(hù)id設(shè)為session_id;
2)如果考慮多端登錄的情況,則session_id中必須包含每個(gè)端的信息,以避免多端快照相互影響;
3)如果不心疼內(nèi)存,也可以每次隨機(jī)一個(gè)字符串作為session_id,并設(shè)置一個(gè)足夠長(zhǎng)的過(guò)期時(shí)間,讓快照自然過(guò)期。
以上設(shè)計(jì):其實(shí)系統(tǒng)計(jì)算量最大的時(shí)刻就是拉取第一頁(yè),構(gòu)建快照的開(kāi)銷(xiāo)。
目前的線上數(shù)據(jù),對(duì)于只關(guān)注不到10個(gè)主播的觀眾(這也是大多數(shù)場(chǎng)景),拉取第一頁(yè)的QPS可以達(dá)到1.5萬(wàn)。如果將第二頁(yè)以后的請(qǐng)求也算進(jìn)來(lái),F(xiàn)eed流的綜合QPS可以達(dá)到更高水平,支撐目前的用戶(hù)規(guī)模已經(jīng)綽綽有余。如果我們拉取第一頁(yè)時(shí)只獲取到前10條即可直接返回,將構(gòu)建快照操作改為異步,也許QPS可以更高一些,這可能是后續(xù)的優(yōu)化點(diǎn)。
8、本文小結(jié)
幾乎所有基于時(shí)間線和關(guān)注關(guān)系的Feed流都逃不開(kāi)三種基本設(shè)計(jì)模式:
1)讀擴(kuò)散;
2)寫(xiě)擴(kuò)散;
3)讀寫(xiě)混合。
具體到實(shí)際業(yè)務(wù)中,可能會(huì)有更復(fù)雜的場(chǎng)景,比如本文所說(shuō)的:
1)狀態(tài)流轉(zhuǎn)影響排序;
2)微博朋友圈場(chǎng)景中會(huì)有廣告接入、特別關(guān)注、熱點(diǎn)話(huà)題等可能影響到Feed流排序的因素。
這些場(chǎng)景就只能根據(jù)業(yè)務(wù)需求,做相對(duì)應(yīng)的變通了。
附錄:更多社交應(yīng)用架構(gòu)設(shè)計(jì)文章
《淺談IM系統(tǒng)的架構(gòu)設(shè)計(jì)》
《簡(jiǎn)述移動(dòng)端IM開(kāi)發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶(hù)端》
《一套海量在線用戶(hù)的移動(dòng)端IM架構(gòu)設(shè)計(jì)實(shí)踐分享(含詳細(xì)圖文)》
《一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案》
《從零到卓越:京東客服即時(shí)通訊系統(tǒng)的技術(shù)架構(gòu)演進(jìn)歷程》
《蘑菇街即時(shí)通訊/IM服務(wù)器開(kāi)發(fā)之架構(gòu)選擇》
《騰訊QQ1.4億在線用戶(hù)的技術(shù)挑戰(zhàn)和架構(gòu)演進(jìn)之路PPT》
《微信后臺(tái)基于時(shí)間序的海量數(shù)據(jù)冷熱分級(jí)架構(gòu)設(shè)計(jì)實(shí)踐》
《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)(演講全文)》
《如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)》》
《快速裂變:見(jiàn)證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)》
《移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?》
《現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討》
《微信朋友圈千億訪問(wèn)量背后的技術(shù)挑戰(zhàn)和實(shí)踐總結(jié)》
《以微博類(lèi)應(yīng)用場(chǎng)景為例,總結(jié)海量社交系統(tǒng)的架構(gòu)設(shè)計(jì)步驟》
《子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐》
《知乎技術(shù)分享:從單機(jī)到2000萬(wàn)QPS并發(fā)的Redis高性能緩存實(shí)踐之路》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(容災(zāi)方案篇)》
《一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐》
《社交軟件紅包技術(shù)解密(一):全面解密QQ紅包技術(shù)方案——架構(gòu)、技術(shù)實(shí)現(xiàn)等》
《社交軟件紅包技術(shù)解密(二):解密微信搖一搖紅包從0到1的技術(shù)演進(jìn)》
《社交軟件紅包技術(shù)解密(三):微信搖一搖紅包雨背后的技術(shù)細(xì)節(jié)》
《社交軟件紅包技術(shù)解密(四):微信紅包系統(tǒng)是如何應(yīng)對(duì)高并發(fā)的》
《社交軟件紅包技術(shù)解密(五):微信紅包系統(tǒng)是如何實(shí)現(xiàn)高可用性的》
《社交軟件紅包技術(shù)解密(六):微信紅包系統(tǒng)的存儲(chǔ)層架構(gòu)演進(jìn)實(shí)踐》
《社交軟件紅包技術(shù)解密(七):支付寶紅包的海量高并發(fā)技術(shù)實(shí)踐》
《社交軟件紅包技術(shù)解密(八):全面解密微博紅包技術(shù)方案》
《社交軟件紅包技術(shù)解密(九):談?wù)勈諵紅包的功能邏輯、容災(zāi)、運(yùn)維、架構(gòu)等》
《從游擊隊(duì)到正規(guī)軍(一):馬蜂窩旅游網(wǎng)的IM系統(tǒng)架構(gòu)演進(jìn)之路》
《從游擊隊(duì)到正規(guī)軍(二):馬蜂窩旅游網(wǎng)的IM客戶(hù)端架構(gòu)演進(jìn)和實(shí)踐總結(jié)》
《從游擊隊(duì)到正規(guī)軍(三):基于Go的馬蜂窩旅游網(wǎng)分布式IM系統(tǒng)技術(shù)實(shí)踐》
《瓜子IM智能客服系統(tǒng)的數(shù)據(jù)架構(gòu)設(shè)計(jì)(整理自現(xiàn)場(chǎng)演講,有配套PPT)》
《阿里釘釘技術(shù)分享:企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過(guò)人之處》
《微信后臺(tái)基于時(shí)間序的新一代海量數(shù)據(jù)存儲(chǔ)架構(gòu)的設(shè)計(jì)實(shí)踐》
《阿里技術(shù)分享:電商IM消息平臺(tái),在群聊、直播場(chǎng)景下的技術(shù)實(shí)踐》
《一套億級(jí)用戶(hù)的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)、服務(wù)拆分等》
《一套億級(jí)用戶(hù)的IM架構(gòu)技術(shù)干貨(下篇):可靠性、有序性、弱網(wǎng)優(yōu)化等》
《從新手到專(zhuān)家:如何設(shè)計(jì)一套億級(jí)消息量的分布式IM系統(tǒng)》
《企業(yè)微信的IM架構(gòu)設(shè)計(jì)揭秘:消息模型、萬(wàn)人群、已讀回執(zhí)、消息撤回等》
《融云技術(shù)分享:全面揭秘億級(jí)IM消息的可靠投遞機(jī)制》
《IM開(kāi)發(fā)技術(shù)學(xué)習(xí):揭秘微信朋友圈這種信息推流背后的系統(tǒng)設(shè)計(jì)》
>>?更多同類(lèi)文章 ……
本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。同步發(fā)布鏈接是:http://www.52im.net/thread-3675-1-1.html