天天看點

深度 | 資料人看Feed流——架構實踐

深度 | 資料人看Feed流——架構實踐

作者:阿裡雲資料庫産品事業部技術專家 天引

背景

Feed流:可以了解為資訊流,解決的是資訊生産者與資訊消費者之間的資訊傳遞問題。

我們常見的Feed流場景有:

手機淘寶,微淘提供給消費者的首頁商品資訊,使用者關注店鋪的新消息等

微信朋友圈,及時擷取朋友分享的資訊

微網誌,粉絲擷取關注明星、大V的資訊

頭條,使用者擷取系統推薦的新聞、評論、八卦

關于Feed流的架構設計,包括以上場景中的很多業内專家給出了相應的思考、設計和實踐。

作者本人是大資料方向出身的技術人,所在的團隊參與了阿裡手淘、微淘Feed流的存儲層相關服務,阿裡雲的HBase/Lindorm資料存儲産品在公有雲上也支援着Soul、趣頭條、惠頭條等一些受歡迎的新媒體、社交類産品。

我們在資料存儲産品的功能、性能、可用性上的一些了解,希望對真實落地一個Feed流架構可以有一些幫助,以及一起探讨Feed流的未來以及資料産品如何幫助Feed流進一步疊代。

本文希望可以提供兩點價值:

1、Feed流目前的主流架構以及落地方案

2、一個初創公司如何選擇Feed流的架構演進路徑

業務分析

Feed流參與者的價值:

  • 資訊生産者

希望資訊支援格式豐富(文字、圖檔、視訊),釋出流暢(生産資訊的可用性),訂閱者及時收到消息(時效性),訂閱者不漏消息(傳遞的可靠性)

  • 資訊消費者

希望及時收到關注的消息(時效性),希望不錯過朋友、偶像的消息(傳遞的可靠性),希望獲得有價值的消息(解決資訊過載)

  • 平台

希望吸引更多的生産者和消費者(PV、UV),使用者更長的停留時間,廣告、商品更高的轉化率

Feed資訊傳遞方式:

一種是基于關系的消息傳遞,關系通過加好友、關注、訂閱等方式建立,可能是雙向的也可能是單向的。一種是基于推薦算法的,系統根據使用者畫像、消息畫像利用标簽分類或者協同過濾等算法向使用者推送消息。微信和微網誌偏向于基于關系,頭條、抖音偏向于基于推薦。

Feed流的技術難點:

網際網路場景總是需要一定規模才能展現出技術的瓶頸,下面我們先看兩組公開資料:

新浪微網誌為例,作為移動社交時代的重量級社交分享平台,2017年初日活躍使用者1.6億,月活躍使用者近3.3億,每天新增數億條資料,總資料量達千億級,核心單個業務的後端資料通路QPS高達百萬級。(來自 《Feed系統架構與Feed緩存模型》)

截止2016年12月底,今日頭條日活躍使用者7800W,月活躍使用者1.75億,單使用者平均使用時長76分鐘,使用者行為峰值150w+msg/s,每天訓練資料300T+(壓縮後),機器規模萬級别

(來自《今日頭條推薦系統架構設計實踐》:

https://yq.aliyun.com/download/602

上面還是兩大巨頭的曆史名額,假設一條消息1KB那麼千億消息約93TB的資料量,日增量在幾百GB規模且QPS高達百萬,是以需要一個具備高讀寫吞吐,擴充性良好的分布式存儲系統。使用者浏覽新消息期望百毫秒響應,希望新消息在秒級或者至少1分鐘左右可見,對系統的實時性要求很高,這裡需要多級的緩存架構。系統必須具備高可用,良好的容錯性。最後這個系統最好不要太貴。

是以我們需要一個高吞吐、易擴充、低延遲、高可用、低成本的Feed流架構

主流架構

圖1是對Feed流的最簡單抽象,完成一個從生産者向消費者傳遞消息的過程。

深度 | 資料人看Feed流——架構實踐

圖1:Feed流簡單抽象

消息和關系

首先,使用者在APP側獲得的是一個Feed ID清單,這個清單不一定包含了所有的新消息,使用者也不一定每一個都打開浏覽,如果傳遞整個消息非常浪費資源,是以産生出來的消息首先生成主體和索引兩個部分,其中索引包含了消息ID和中繼資料。其次一個應用總是存在關系,基于關系的傳遞是必不可少的,也是以一定有一個關系的存儲和查詢服務。

深度 | 資料人看Feed流——架構實踐

圖2:Feed流消息、關系的存儲

消息本身應該算是一種半結構化資料(包含文字,圖檔,短視訊,音頻,中繼資料等)。其讀寫吞吐量要求高,讀寫比例需要看具體場景。總的存儲空間大,需要很好的擴充性來支撐業務增長。消息可能會有多次更新,比如内容修改,浏覽數,點贊數,轉發數(成熟的系統會獨立一個counter子產品來服務這些中繼資料)以及标記删除。消息一般不會永久儲存,可能要在1年或者3年後删除。

綜上,個人推薦使用HBase存儲

HBase支援結構化和半結構化資料;

具有非常好的寫入性能,特别對于Feed流場景可以利用批量寫接口單機(32核64GB)達到幾十萬的寫入效率;

HBase具備非常平滑的水準擴充能力,自動進行Sharding和Balance;

HBase内置的BlockCache加上SSD盤可以提供ms級的高并發讀;

HBase的TTL特性可以自動的淘汰過期資料;

利用資料複制搭建一個冷熱分離系統,新消息存儲在擁有SSD磁盤和大規格緩存的熱庫,舊資料存儲在冷庫。

運用編碼壓縮有效的控制存儲成本,見《HBase優化之路-合理的使用編碼壓縮》

https://yq.aliyun.com/articles/702370
深度 | 資料人看Feed流——架構實踐

圖3:使用HBase存儲Feed流消息

對于關系服務,其寫入操作是建立關系和删除關系,讀取操作是擷取關系清單,邏輯上僅需要一個KV系統。如果資料量較少可以使用RDS,如果資料量較大推薦使用HBase。如果對關系的QPS壓力大可以考慮用Redis做緩存。

深度 | 資料人看Feed流——架構實踐

圖4:使用者關系存儲

消息傳遞

講到Feed流一定會有關于推模式和拉模式的讨論,推模式是把消息複制N次發送到N個使用者的收信箱,使用者想看消息時從自己的收信箱直接擷取。拉模式相反,生産者的消息寫入自己的發信箱,使用者想看消息時從關注的M個發信箱中收集消息。

深度 | 資料人看Feed流——架構實踐

圖5:消息傳遞的推模式和拉模式

推模式實作相對簡單,時效性也比較好。拉模式要想獲得好的性能需要多級的緩存架構。推模式重寫,拉模式重讀,Feed流場景下寫的聚合效果要優于讀,寫可以大批量聚合。N越大,寫入造成的資料備援就越大。M越大,讀消耗的資源越大。

随着業務的增長,推模式資源浪費會越發嚴重。原因在于兩點:第一存在着大量的僵屍賬号,以及大比例的非活躍使用者幾天或者半個月才登陸一次;第二資訊過載,資訊太多,重複資訊太多,垃圾資訊太多,使用者感覺有用的資訊少,消息的閱讀比例低。這種情況下推模式相當一部分在做無用功,白白浪費系統資源。

是推?是拉?還是混合?沒有最好的架構,隻有适合的場景~

基于關系的傳遞

圖6是純推模式的架構,該架構有3個關鍵的部分

異步化。生産者送出消息首先寫入一個隊列,成功則表示釋出成功,Dispatcher子產品會異步的處理消息。這一點非常關鍵,首先生産者的消息釋出體驗非常好,不需要等待消息同步到粉絲的收信箱,釋出延遲低成功率高;其次Dispatcher可以控制隊列的處理速度,可以有效的控制大V賬号造成的脈沖壓力。

多級隊列。Dispatcher可以根據消費者的狀态,資訊的分類等劃分不同的處理方式,配置設定不同的資源。比如對于大V賬号的消息,目前活躍使用者選擇直接發送,保障消息的時效性,非活躍使用者放入隊列延遲發送。比如轉發多的消息可以優先處理等。隊列裡的消息可以采用批量聚合寫的方式提高吞吐。

收信箱。假如有兩億使用者,每個使用者保留最新2000條推送消息。即便存儲的是索引也是千億的規模。收信箱一般的表結構為使用者ID+消息序列 + 消息ID + 消息中繼資料,消息序列是一個遞增的ID,需要存儲一個偏移量表示上次讀到的消息序列ID。使用者讀取最新消息 select * from inbox where 消息序列 > offset。

深度 | 資料人看Feed流——架構實踐

圖6:基于關系傳遞的純推模式

推薦使用HBase實作收信箱

HBase單機批量寫能力在幾十萬并且可以水準擴充。

HBase的高效字首掃描非常适合讀取最新的消息。

HBase的TTL功能可以對資料定義生命周期,高效的淘汰過期資料。

HBase的Filter過濾器和二級索引可以有效的實作Inbox的搜尋能力。

消費者收信箱hbase表設計如下,其中序列号要保證遞增,一般用時間戳即可,特别高頻情況下可以用一個RDS來制造序列号

Rowkey 消息中繼資料列 狀态列 其它列
MD5(使用者ID)+使用者ID+序列号 消息ID、作者、釋出時間、關鍵字等 已讀、未讀

圖7是推拉結合的模式

增加發信箱,大V的釋出進入其獨立的發信箱。非大V的釋出直接發送到使用者的收信箱。其好處是解決大量的僵屍賬号和非活躍賬号的問題。使用者隻有在請求新消息的時候(比如登陸、下拉消息框)才會去消耗系統資源。

發信箱的多級緩存架構。一個大V可能有百萬粉絲,一條熱點消息的傳播視窗也會非常短,即短時間内會對發信箱中的同一條消息大量重複讀取,對系統挑戰很大。終态下我們可能會選擇兩級緩存,收信箱資料還是要持久化的,否則更新或者當機時資料就丢失了,是以第一層是一個分布式資料存儲,這個存儲推薦使用HBase,原因和Inbox類似。

第二層使用redis緩存加速,但是大V過大可能造成熱點問題還需要第三層本地緩存。緩存層的優化主要包括兩個方向:第一提高緩存命中率,常用的方式是對資料進行編碼壓縮,第二保障緩存的可用性,這裡涉及到對緩存的備援。

深度 | 資料人看Feed流——架構實踐

圖7:基于關系傳遞的推拉混合模式

基于推薦的傳遞

圖8是基于推薦的模型,可以看出它是在推拉結合的模式上融合了推薦系統。

引入畫像系統,儲存使用者畫像、消息畫像(簡單情況下消息畫像可以放在消息中繼資料中)。畫像用于推薦系統算法的輸入。

引入了臨時收信箱,在資訊過載的場景中,非大V的消息也是總量很大,其中不免充斥着垃圾、備援消息,是以直接進入使用者收信箱不太合适。

收信箱和發信箱都需要有良好的搜尋能力,這是推薦系統高效運作的關鍵。Outbox有緩存層,索引可以做到緩存裡面;Inbox一般情況下二級索引可以滿足大部分需求,但如果使用者希望有全文索引或者任意次元的檢索能力,還需要引入搜尋系統如Solr/ES

深度 | 資料人看Feed流——架構實踐

圖8:基于推薦的Feed流架構

使用者畫像使用HBase存儲

畫像一般是稀疏表,畫像總次元可能在200+甚至更多,但單個使用者的次元可能在幾十,并且次元可能随業務不斷變化。那麼HBase的Schema free和稀疏表的能力非常适合這個場景,易用且節省大量存儲空間。

對畫像的通路一般是單行讀,hbase本身單行Get的性能就非常好。阿裡雲HBase在這個方向上做了非常多的優化,包括CCSMAP、SharedBucketCache、MemstoreBloomFilter、Index Encoding等,可以達到平均RT=1-2ms,單庫99.9% <100ms。阿裡内部利用雙叢集Dual Service可以做到 99.9% < 30ms,這一能力我們也在努力推到公有雲。hbase的讀吞吐随機器數量水準擴充。

臨時收信箱使用雲HBase

HBase的讀寫高吞吐、低延遲能力,這裡不再重複。

HBase提供Filter和全局二級索引,滿足不同量級的搜尋需求。

阿裡雲HBase融合HBase與Solr能力,提供低成本的全文索引、多元索引能力。

初創公司的疊代路徑

在業務發展的初期,使用者量和資源都沒有那麼多,團隊的人力投入也是有限的,不可能一上來就搞一個特别複雜的架構,“夠用”就行了,重要的是

可以快速的傳遞

系統要穩定

未來可以從容的疊代,避免推倒重來

本人水準有限,根據自身的經驗向大家推薦一種疊代路徑以供參考,如有不同意見歡迎交流

起步架構如圖9,使用雲Kafka+雲HBase。如果對Inbox有檢索需求,建議使用HBase的scan+filter即可。

消息分為主體和索引

采用純推的模式

采用異步化

深度 | 資料人看Feed流——架構實踐

圖9 起步架構

資料量逐漸增大後,對推模式進一步疊代,主要需求是:

控制大V造成的寫入脈沖高峰

控制存儲成本

提升讀寫性能

提升一定的Inbox搜尋能力

進一步的疊代架構如圖10

采用多級隊列解決大V問題

采用冷熱分離降低存儲成本

此時Inbox中的消息也很多,對搜尋的需求增強,僅僅Scan+Filter不夠,可能需要二級索引

深度 | 資料人看Feed流——架構實踐

圖10 純推模式的演進

業務迅猛發展,消息和使用者增長迅速,僵屍賬号、非活躍賬号較多,資訊過載嚴重

采用推拉結合模式

引入推薦系統

Outbox采用多級緩存提高讀取性能

Inbox增加二級索引提升搜尋能力

使用雲Kafka+雲HBase+雲Redis

深度 | 資料人看Feed流——架構實踐

圖11:基于推薦的推拉混合架構

總結

Feed資訊流是網際網路場景中非常普遍的場景,遍布于電商、社交、新媒體等APP,是以研究Feed流是非常有價值的一件事情。

本文總結了Feed流的業務場景和主流架構,分析了不同場景、體量下技術的難點與瓶頸。對Dispatcher、Inbox、Outout幾個元件進行了詳細的演進介紹,提供了基于雲環境的落地方案。本人水準有限,希望可以抛磚引玉,歡迎大家一起探讨。

Feed流的架構演進還在持續,不同業務場景下還有哪些缺陷和痛點?資料産品如何從功能和性能上演進來支撐Feed流的持續發展?在這些問題的驅動下,雲HBase未來将會大力投入到Feed流場景的持續優化和賦能!

阿裡雲HBase:

https://cn.aliyun.com/product/hbase

參考文獻

[1] Feed架構-我們做錯了什麼:

https://timyang.net/architecture/feed-data-arch-cons/

[2] Feed系統架構與Feed緩存模型

[3] 今日頭條推薦系統架構設計實踐:

[4] 新浪微網誌架構和FEED架構分析:

http://blog.sina.com.cn/s/blog_53b95aec0100ujim.html

[5] feed流個性化推薦架構和算法分享

https://blog.csdn.net/baymax_007/article/details/89853030