Feed流:可以理解為信息流役纹,解決的是信息生產(chǎn)者與信息消費(fèi)者之間的信息傳遞問題护戳。
我們常見的Feed流場景有:
1 手淘,微淘提供給消費(fèi)者的首頁商品信息缭付,用戶關(guān)注店鋪的新消息等
2 微信朋友圈鉴竭,及時(shí)獲取朋友分享的信息
3 微博歧譬,粉絲獲取關(guān)注明星、大V的信息
4 頭條搏存,用戶獲取系統(tǒng)推薦的新聞瑰步、評論、八卦
關(guān)于Feed流的架構(gòu)設(shè)計(jì)璧眠,包括以上場景中的很多業(yè)內(nèi)專家給出了相應(yīng)的思考缩焦、設(shè)計(jì)和實(shí)踐读虏。本人是大數(shù)據(jù)方向出身的技術(shù)人,所在的團(tuán)隊(duì)參與了阿里手淘袁滥、微淘Feed流的存儲層相關(guān)服務(wù)盖桥,我們的HBase/Lindorm數(shù)據(jù)存儲產(chǎn)品在公有云上也支持著Soul、趣頭條呻拌、惠頭條等一些受歡迎的新媒體葱轩、社交類產(chǎn)品。我們在數(shù)據(jù)存儲產(chǎn)品的功能藐握、性能、可用性上的一些理解垃喊,希望對真實(shí)落地一個(gè)Feed流架構(gòu)可以有一些幫助猾普,以及一起探討Feed流的未來以及數(shù)據(jù)產(chǎn)品如何幫助Feed流進(jìn)一步迭代。
本文希望可以提供兩點(diǎn)價(jià)值:
1 Feed流當(dāng)前的主流架構(gòu)以及落地方案
2 一個(gè)初創(chuàng)公司如何選擇Feed流的架構(gòu)演進(jìn)路徑
業(yè)務(wù)分析
Feed流參與者的價(jià)值
信息生產(chǎn)者
希望信息支持格式豐富(文字本谜、圖片初家、視頻),發(fā)布流暢(生產(chǎn)信息的可用性)乌助,訂閱者及時(shí)收到消息(時(shí)效性)溜在,訂閱者不漏消息(傳遞的可靠性)
信息消費(fèi)者
希望及時(shí)收到關(guān)注的消息(時(shí)效性),希望不錯(cuò)過朋友他托、偶像的消息(傳遞的可靠性)掖肋,希望獲得有價(jià)值的消息(解決信息過載)
平臺
希望吸引更多的生產(chǎn)者和消費(fèi)者(PV、UV)赏参,用戶更長的停留時(shí)間志笼,廣告、商品更高的轉(zhuǎn)化率
Feed信息傳遞方式
一種是基于關(guān)系的消息傳遞把篓,關(guān)系通過加好友纫溃、關(guān)注、訂閱等方式建立韧掩,可能是雙向的也可能是單向的紊浩。一種是基于推薦算法的,系統(tǒng)根據(jù)用戶畫像疗锐、消息畫像利用標(biāo)簽分類或者協(xié)同過濾等算法向用戶推送消息坊谁。微信和微博偏向于基于關(guān)系,頭條窒悔、抖音偏向于基于推薦呜袁。
Feed流的技術(shù)難點(diǎn)
互聯(lián)網(wǎng)場景總是需要一定規(guī)模才能體現(xiàn)出技術(shù)的瓶頸,下面我們先看兩組公開數(shù)據(jù):
新浪微博為例简珠,作為移動(dòng)社交時(shí)代的重量級社交分享平臺阶界,2017年初日活躍用戶1.6億虹钮,月活躍用戶近3.3億,每天新增數(shù)億條數(shù)據(jù)膘融,總數(shù)據(jù)量達(dá)千億級芙粱,核心單個(gè)業(yè)務(wù)的后端數(shù)據(jù)訪問QPS高達(dá)百萬級
(來自?Feed系統(tǒng)架構(gòu)與Feed緩存模型)
截止2016年12月底,頭條日活躍用戶7800W氧映,月活躍用戶1.75億春畔,單用戶平均使用時(shí)長76分鐘,用戶行為峰值150w+msg/s岛都,每天訓(xùn)練數(shù)據(jù)300T+(壓縮后)律姨,機(jī)器規(guī)模萬級別
(來自?今日頭條推薦系統(tǒng)架構(gòu)設(shè)計(jì)實(shí)踐)
上面還是兩大巨頭的歷史指標(biāo),假設(shè)一條消息1KB那么千億消息約93TB的數(shù)據(jù)量臼疫,日增量在幾百GB規(guī)模且QPS高達(dá)百萬择份,因此需要一個(gè)具備高讀寫吞吐,擴(kuò)展性良好的分布式存儲系統(tǒng)烫堤。用戶瀏覽新消息期望百毫秒響應(yīng)荣赶,希望新消息在秒級或者至少1分鐘左右可見,對系統(tǒng)的實(shí)時(shí)性要求很高鸽斟,這里需要多級的緩存架構(gòu)拔创。系統(tǒng)必須具備高可用,良好的容錯(cuò)性富蓄。最后這個(gè)系統(tǒng)最好不要太貴剩燥。
因此我們需要一個(gè)高吞吐、易擴(kuò)展格粪、低延遲躏吊、高可用、低成本的Feed流架構(gòu)
主流架構(gòu)
圖1是對Feed流的最簡單抽象帐萎,完成一個(gè)從生產(chǎn)者向消費(fèi)者傳遞消息的過程比伏。
圖1 Feed流簡單抽象
消息和關(guān)系
首先,用戶在APP側(cè)獲得的是一個(gè)Feed ID列表疆导,這個(gè)列表不一定包含了所有的新消息赁项,用戶也不一定每一個(gè)都打開瀏覽,如果傳遞整個(gè)消息非常浪費(fèi)資源澈段,因此產(chǎn)生出來的消息首先生成主體和索引兩個(gè)部分悠菜,其中索引包含了消息ID和元數(shù)據(jù)。其次一個(gè)應(yīng)用總是存在關(guān)系败富,基于關(guān)系的傳遞是必不可少的悔醋,也因此一定有一個(gè)關(guān)系的存儲和查詢服務(wù)。
圖2 Feed流消息兽叮、關(guān)系的存儲
消息本身應(yīng)該算是一種半結(jié)構(gòu)化數(shù)據(jù)(包含文字芬骄,圖片猾愿,短視頻,音頻账阻,元數(shù)據(jù)等)蒂秘。其讀寫吞吐量要求高,讀寫比例需要看具體場景淘太∫錾總的存儲空間大,需要很好的擴(kuò)展性來支撐業(yè)務(wù)增長蒲牧。消息可能會有多次更新撇贺,比如內(nèi)容修改,瀏覽數(shù)冰抢,點(diǎn)贊數(shù)显熏,轉(zhuǎn)發(fā)數(shù)(成熟的系統(tǒng)會獨(dú)立一個(gè)counter模塊來服務(wù)這些元數(shù)據(jù))以及標(biāo)記刪除。消息一般不會永久保存晒屎,可能要在1年或者3年后刪除。
綜上缓升,個(gè)人推薦使用HBase存儲
HBase支持結(jié)構(gòu)化和半結(jié)構(gòu)化數(shù)據(jù)鼓鲁;
具有非常好的寫入性能,特別對于Feed流場景可以利用批量寫接口單機(jī)(32核64GB)達(dá)到幾十萬的寫入效率港谊;
HBase具備非常平滑的水平擴(kuò)展能力骇吭,自動(dòng)進(jìn)行Sharding和Balance;
HBase內(nèi)置的BlockCache加上SSD盤可以提供ms級的高并發(fā)讀歧寺;
HBase的TTL特性可以自動(dòng)的淘汰過期數(shù)據(jù)燥狰;
利用數(shù)據(jù)復(fù)制搭建一個(gè)冷熱分離系統(tǒng),新消息存儲在擁有SSD磁盤和大規(guī)格緩存的熱庫斜筐,舊數(shù)據(jù)存儲在冷庫龙致。
運(yùn)用編碼壓縮有效的控制存儲成本,見HBase優(yōu)化之路-合理的使用編碼壓縮
圖3 使用HBase存儲Feed流消息
對于關(guān)系服務(wù)顷链,其寫入操作是建立關(guān)系和刪除關(guān)系目代,讀取操作是獲取關(guān)系列表,邏輯上僅需要一個(gè)KV系統(tǒng)嗤练。如果數(shù)據(jù)量較少可以使用RDS榛了,如果數(shù)據(jù)量較大推薦使用HBase。如果對關(guān)系的QPS壓力大可以考慮用Redis做緩存煞抬。
圖4 用戶關(guān)系存儲
消息傳遞
講到Feed流一定會有關(guān)于推模式和拉模式的討論霜大,推模式是把消息復(fù)制N次發(fā)送到N個(gè)用戶的收信箱,用戶想看消息時(shí)從自己的收信箱直接獲取革答。拉模式相反战坤,生產(chǎn)者的消息寫入自己的發(fā)信箱曙强,用戶想看消息時(shí)從關(guān)注的M個(gè)發(fā)信箱中收集消息。
圖5 消息傳遞的推模式和拉模式
推模式實(shí)現(xiàn)相對簡單湖笨,時(shí)效性也比較好旗扑。拉模式要想獲得好的性能需要多級的緩存架構(gòu)。推模式重寫慈省,拉模式重讀臀防,F(xiàn)eed流場景下寫的聚合效果要優(yōu)于讀,寫可以大批量聚合边败。N越大袱衷,寫入造成的數(shù)據(jù)冗余就越大。M越大笑窜,讀消耗的資源越大致燥。
隨著業(yè)務(wù)的增長,推模式資源浪費(fèi)會越發(fā)嚴(yán)重排截。原因在于兩點(diǎn):第一存在著大量的僵尸賬號嫌蚤,以及大比例的非活躍用戶幾天或者半個(gè)月才登陸一次;第二信息過載断傲,信息太多脱吱,重復(fù)信息太多,垃圾信息太多认罩,用戶感覺有用的信息少箱蝠,消息的閱讀比例低。這種情況下推模式相當(dāng)一部分在做無用功垦垂,白白浪費(fèi)系統(tǒng)資源宦搬。
是推?是拉劫拗?還是混合间校?沒有最好的架構(gòu),只有適合的場景~
基于關(guān)系的傳遞
圖6是純推模式的架構(gòu)杨幼,該架構(gòu)有3個(gè)關(guān)鍵的部分
異步化撇簿。生產(chǎn)者提交消息首先寫入一個(gè)隊(duì)列,成功則表示發(fā)布成功差购,Dispatcher模塊會異步的處理消息四瘫。這一點(diǎn)非常關(guān)鍵,首先生產(chǎn)者的消息發(fā)布體驗(yàn)非常好欲逃,不需要等待消息同步到粉絲的收信箱找蜜,發(fā)布延遲低成功率高;其次Dispatcher可以控制隊(duì)列的處理速度稳析,可以有效的控制大V賬號造成的脈沖壓力洗做。
多級隊(duì)列弓叛。Dispatcher可以根據(jù)消費(fèi)者的狀態(tài),信息的分類等劃分不同的處理方式诚纸,分配不同的資源撰筷。比如對于大V賬號的消息,當(dāng)前活躍用戶選擇直接發(fā)送畦徘,保障消息的時(shí)效性毕籽,非活躍用戶放入隊(duì)列延遲發(fā)送。比如轉(zhuǎn)發(fā)多的消息可以優(yōu)先處理等井辆。隊(duì)列里的消息可以采用批量聚合寫的方式提高吞吐关筒。
收信箱。假如有兩億用戶杯缺,每個(gè)用戶保留最新2000條推送消息蒸播。即便存儲的是索引也是千億的規(guī)模痊乾。收信箱一般的表結(jié)構(gòu)為用戶ID+消息序列 + 消息ID + 消息元數(shù)據(jù)圈浇,消息序列是一個(gè)遞增的ID,需要存儲一個(gè)偏移量表示上次讀到的消息序列ID溉痢。用戶讀取最新消息 select * from inbox where 消息序列 > offset塘揣。
圖6 基于關(guān)系傳遞的純推模式
推薦使用HBase實(shí)現(xiàn)收信箱
HBase單機(jī)批量寫能力在幾十萬并且可以水平擴(kuò)展蜡塌。
HBase的高效前綴掃描非常適合讀取最新的消息。
HBase的TTL功能可以對數(shù)據(jù)定義生命周期勿负,高效的淘汰過期數(shù)據(jù)。
HBase的Filter過濾器和二級索引可以有效的實(shí)現(xiàn)Inbox的搜索能力劳曹。
消費(fèi)者收信箱hbase表設(shè)計(jì)如下奴愉,其中序列號要保證遞增,一般用時(shí)間戳即可铁孵,特別高頻情況下可以用一個(gè)RDS來制造序列號
Rowkey消息元數(shù)據(jù)列狀態(tài)列其它列
MD5(用戶ID)+用戶ID+序列號消息ID锭硼、作者、發(fā)布時(shí)間蜕劝、關(guān)鍵字等已讀檀头、未讀
圖7是推拉結(jié)合的模式
增加發(fā)信箱,大V的發(fā)布進(jìn)入其獨(dú)立的發(fā)信箱岖沛。非大V的發(fā)布直接發(fā)送到用戶的收信箱暑始。其好處是解決大量的僵尸賬號和非活躍賬號的問題。用戶只有在請求新消息的時(shí)候(比如登陸婴削、下拉消息框)才會去消耗系統(tǒng)資源廊镜。
發(fā)信箱的多級緩存架構(gòu)。一個(gè)大V可能有百萬粉絲唉俗,一條熱點(diǎn)消息的傳播窗口也會非常短嗤朴,即短時(shí)間內(nèi)會對發(fā)信箱中的同一條消息大量重復(fù)讀取配椭,對系統(tǒng)挑戰(zhàn)很大。終態(tài)下我們可能會選擇兩級緩存雹姊,收信箱數(shù)據(jù)還是要持久化的股缸,否則升級或者宕機(jī)時(shí)數(shù)據(jù)就丟失了,所以第一層是一個(gè)分布式數(shù)據(jù)存儲吱雏,這個(gè)存儲推薦使用HBase敦姻,原因和Inbox類似。第二層使用redis緩存加速坎背,但是大V過大可能造成熱點(diǎn)問題還需要第三層本地緩存替劈。緩存層的優(yōu)化主要包括兩個(gè)方向:第一提高緩存命中率,常用的方式是對數(shù)據(jù)進(jìn)行編碼壓縮得滤,第二保障緩存的可用性陨献,這里涉及到對緩存的冗余。
圖7 基于關(guān)系傳遞的推拉混合模式
基于推薦的傳遞
圖8是基于推薦的模型懂更,可以看出它是在推拉結(jié)合的模式上融合了推薦系統(tǒng)眨业。
引入畫像系統(tǒng),保存用戶畫像沮协、消息畫像(簡單情況下消息畫像可以放在消息元數(shù)據(jù)中)龄捡。畫像用于推薦系統(tǒng)算法的輸入。
引入了臨時(shí)收信箱慷暂,在信息過載的場景中聘殖,非大V的消息也是總量很大,其中不免充斥著垃圾行瑞、冗余消息奸腺,所以直接進(jìn)入用戶收信箱不太合適。
收信箱和發(fā)信箱都需要有良好的搜索能力血久,這是推薦系統(tǒng)高效運(yùn)行的關(guān)鍵突照。Outbox有緩存層,索引可以做到緩存里面氧吐;Inbox一般情況下二級索引可以滿足大部分需求讹蘑,但如果用戶希望有全文索引或者任意維度的檢索能力,還需要引入搜索系統(tǒng)如Solr/ES
圖8 基于推薦的Feed流架構(gòu)
用戶畫像使用HBase存儲
畫像一般是稀疏表筑舅,畫像總維度可能在200+甚至更多座慰,但單個(gè)用戶的維度可能在幾十,并且維度可能隨業(yè)務(wù)不斷變化翠拣。那么HBase的Schema free和稀疏表的能力非常適合這個(gè)場景角骤,易用且節(jié)省大量存儲空間。
對畫像的訪問一般是單行讀,hbase本身單行Get的性能就非常好邦尊。阿里云HBase在這個(gè)方向上做了非常多的優(yōu)化背桐,包括CCSMAP、SharedBucketCache蝉揍、MemstoreBloomFilter链峭、Index Encoding等,可以達(dá)到平均RT=1-2ms又沾,單庫99.9% <100ms弊仪。阿里內(nèi)部利用雙集群Dual Service可以做到 99.9% < 30ms,這一能力我們也在努力推到公有云杖刷。hbase的讀吞吐隨機(jī)器數(shù)量水平擴(kuò)展励饵。
臨時(shí)收信箱使用云HBase
HBase的讀寫高吞吐、低延遲能力滑燃,這里不再重復(fù)役听。
HBase提供Filter和全局二級索引,滿足不同量級的搜索需求表窘。
阿里云HBase融合HBase與Solr能力典予,提供低成本的全文索引、多維索引能力乐严。
初創(chuàng)公司的迭代路徑
在業(yè)務(wù)發(fā)展的初期瘤袖,用戶量和資源都沒有那么多,團(tuán)隊(duì)的人力投入也是有限的昂验,不可能一上來就搞一個(gè)特別復(fù)雜的架構(gòu)捂敌,“夠用”就行了,重要的是
可以快速的交付
系統(tǒng)要穩(wěn)定
未來可以從容的迭代既琴,避免推倒重來
本人水平有限黍匾,根據(jù)自身的經(jīng)驗(yàn)向大家推薦一種迭代路徑以供參考,如有不同意見歡迎交流
起步架構(gòu)如圖9呛梆,使用云Kafka+云HBase。如果對Inbox有檢索需求磕诊,建議使用HBase的scan+filter即可填物。
消息分為主體和索引
采用純推的模式
采用異步化
圖9 起步架構(gòu)
數(shù)據(jù)量逐漸增大后,對推模式進(jìn)一步迭代霎终,主要需求是
控制大V造成的寫入脈沖高峰
控制存儲成本
提升讀寫性能
提升一定的Inbox搜索能力
進(jìn)一步的迭代架構(gòu)如圖10
消息分為主體和索引
采用純推的模式
采用異步化
采用多級隊(duì)列解決大V問題
采用冷熱分離降低存儲成本
此時(shí)Inbox中的消息也很多滞磺,對搜索的需求增強(qiáng),僅僅Scan+Filter不夠莱褒,可能需要二級索引
圖10 純推模式的演進(jìn)
業(yè)務(wù)迅猛發(fā)展击困,消息和用戶增長迅速,僵尸賬號、非活躍賬號較多阅茶,信息過載嚴(yán)重
消息分為主體和索引
采用推拉結(jié)合模式
采用異步化
引入推薦系統(tǒng)
采用冷熱分離降低存儲成本
Outbox采用多級緩存提高讀取性能
Inbox增加二級索引提升搜索能力
使用云Kafka+云HBase+云Redis
圖11 基于推薦的推拉混合架構(gòu)
總結(jié)
Feed信息流是互聯(lián)網(wǎng)場景中非常普遍的場景蛛枚,遍布于電商、社交脸哀、新媒體等APP蹦浦,因此研究Feed流是非常有價(jià)值的一件事情。本文總結(jié)了Feed流的業(yè)務(wù)場景和主流架構(gòu)撞蜂,分析了不同場景盲镶、體量下技術(shù)的難點(diǎn)與瓶頸。對Dispatcher蝌诡、Inbox溉贿、Outout幾個(gè)組件進(jìn)行了詳細(xì)的演進(jìn)介紹,提供了基于云環(huán)境的落地方案浦旱。本人水平有限宇色,希望可以拋磚引玉,歡迎大家一起探討闽寡。Feed流的架構(gòu)演進(jìn)還在持續(xù)代兵,不同業(yè)務(wù)場景下還有哪些缺陷和痛點(diǎn)?數(shù)據(jù)產(chǎn)品如何從功能和性能上演進(jìn)來支撐Feed流的持續(xù)發(fā)展爷狈?在這些問題的驅(qū)動(dòng)下植影,云HBase未來將會大力投入到Feed流場景的持續(xù)優(yōu)化和賦能!