1. 程式人生 > >微博和知乎中的 feed 流是如何實現的

微博和知乎中的 feed 流是如何實現的

談談知乎的Feed。
雖然我不是技術大佬。

簡單來說,Feeds這塊主要包括兩塊內容,就是生成feeds和更新feeds。生成feeds是什麼意思呢,比如我們已經關注的人做了特定操作,我們需要把這些活動加入你的feeds,讓你接收到。更新feeds包括的內容比較多,一種就是你關注點做了更新,比如你新關注了一個人,需要把他的活動加入已有feeds,與此類似,取消關注也一樣;另一種就是你的關注點做了一些更新操作,比如你關注的一個人取消關注了一個問題。

我們先來談feeds生成,使用者A做了某操作,比如關注了一個問題,這時候我們首先找到使用者A的所有關注者,然後給需要推送的關注者推送此操作,大家可以把每個人的feeds簡單想象為一個有序列表,推送很簡單,就是在每個人的列表末尾新增這個操作。怎麼樣,是不是很簡單,:)

然後我們談feeds更新,第一種情況和第二種情況其實都是一樣的,我們需要針對這些活動更新來更新feeds,比如我們新關注了一個人,這時候我們需要取出此人的活動歷史,然後按照時間順序把這些歷史塞到你的feeds中。此操作的複雜度會比較高,需要使用合適的資料結構來達到最佳效能,目前是O(log(N))。

當然,真實情況並沒有這麼簡單,還有很多其他邏輯和注意點,比如我們的feeds需要對多人做同樣的操作做合併(大家可以自行把以上的feeds有序列表變為有序集合),同樣的內容的建立時間是要按最新操作的時間來計算的,一個人連續做很多操作需要對操作做合併等。所有大家看到的feeds相應的儲存考慮到效能都會使用記憶體,除此之外所有的操作都需要做持久化儲存,否則我們也就沒法更新feeds了:)

下面我們談談這裡面的技術挑戰和相關技術,此部分與知乎目前的技術決策和使用技術無關,我給大家分享幾個國外團隊的工程決策和他們的優化手段。

先來談談strava,他們使用了Kafka分散式釋出訂閱訊息系統,這個系統用來事件(event)釋出,還使用了Storm分散式實時計算平臺,這個計算叢集會訂閱Kafka的事件,然後完成相應的處理,在這塊他們做了一個優化,就是一個事件不會推給所有關注者,只會推給活躍的使用者(如何判定一個使用者為活躍的,這就看實際情況和資料自己優化了)。

然後再來談談Instagram,他們產品的讀寫比例達到了100:1,事實上大部分網際網路產品都是這樣,所以這也是推技術更合適的原因,推一次開銷可能大一點,不過推(也就是寫)發生次數大大少於讀,因為有些大牛關注者非常多,達到幾百上千萬,為了進行可靠地推,這個過程都會非同步後臺執行。同樣,我們需要一個任務排程器和訊息佇列,任務排程他們選用了Celery,下面需要選擇一個訊息佇列,Redis依賴訂閱者輪詢,不自帶複製備份,而且強依賴記憶體是個硬傷,不合適;Beanstalk其他方面不錯,可還是不支援複製(Replication),棄掉;最後他們選用了RabbitMQ,快,高效,支援複製,而且和Celery高度相容。

接著談談Pinterest,重心在於建立一個智慧化的feed,也就是feed會包括一些熱點和推薦,而且會根據特定演算法來排序。當事件發生後,會經過一系列流程最後才進入使用者的內容feed,首先經過智慧feed worker來處理,這些worker會接收事件而且根據特定使用者給事件打分,然後這些事件會被插入到一個排好序的feed池中,不同型別的事件會被插入各自的池中,目前他們使用HBase的基於key的排序實現了此優先佇列,接著智慧feed內容生成器接手了,它會從幾個池中根據策略取出feeds甚至剔除一些feeds,最後面向用戶的智慧feed服務會整合舊的feed和新生成的feed,展現給使用者看到的Home Feeds。

最後簡單談談Facebook,使用者量大了之後對工程團隊要求會更高,每個facebook使用者都會有一個屬於自己的獨一無二的動態生成的首頁。很多團隊都會用使用者ID為Key來把feeds存入Key-Value儲存系統,比如Redis,問題是通過網路連線做遠端過程呼叫非常慢,無法滿足實時性的要求,所以facebook團隊也開始使用了嵌入式資料庫,他們也開源了自己在用的
RocksDB


這些內容都在他們的技術部落格裡面有提到,連結在這裡:
Strava Engineering
How Instagram Feeds Work: Celery and RabbitMQ
Making Pinterest
facebook.com/notes/1015

就像電影特效是為劇情服務一樣,技術是為產品服務的。針對不同的業務場景,適合的技術也是不一樣的。隨著產品的調整和業務規模的擴大,相應的技術都會做進化和調整。針對不同的難題,需要提出不同的技術方案,feeds的生成也是這樣,如果有必要,我們也會對這些方案做調整,目的都是一樣,那就是又對又快又穩定。

如果有什麼錯誤,希望大神指出。如果有更好的方案或者建議,歡迎交流。