在互聯網領域,尤其現在的移動互聯網時代,Feed流產品是非常常見的,比如我們每天都會用到的朋友圈,微博,就是一種非常典型的Feed流產品,還有圖片分享網站Pinterest,花瓣網等又是另一種形式的Feed流產品。除此之外,很多App的都會有一個模塊,要么叫動態,要么叫消息廣場,這些也是Feed流產品,可以說,Feed流產品是遍布天下所有的App中。
概念
我們在講如何設計Feed流系統之前,先來看一下Feed流中的一些概念:
- Feed:Feed流中的每一條狀態或者消息都是Feed,比如朋友圈中的一個狀態就是一個Feed,微博中的一條微博就是一個Feed。
- Feed流:持續更新並呈現給用戶內容的信息流。每個人的朋友圈,微博關注頁等等都是一個Feed流。
- Timeline:Timeline其實是一種Feed流的類型,微博,朋友圈都是Timeline類型的Feed流,但是由於Timeline類型出現最早,使用最廣泛,最為人熟知,有時候也用Timeline來表示Feed流。
- 關注頁Timeline:展示其他人Feed消息的頁面,比如朋友圈,微博的首頁等。
- 個人頁Timeline:展示自己發送過的Feed消息的頁面,比如微信中的相冊,微博的個人頁等。
特征
Feed流系統有一些非常典型的特點,比如:
- 多賬號內容流:Feed流系統中肯定會存在成千上萬的賬號,賬號之間可以關注,取關,加好友和拉黑等操作。只要滿足這一條,那么就可以當做Feed流系統來設計。
- 非穩定的賬號關系:由於存在關注,取關等操作,所以系統中的用戶之間的關系就會一直在變化,是一種非穩定的狀態。
- 讀寫比例100:1:讀寫嚴重不平衡,讀多寫少,一般讀寫比例在10:1,甚至100:1以上。
- 消息必達性要求高:比如發送了一條朋友圈后,結果部分朋友看到了,部分朋友沒看到,如果偏偏女朋友沒看到,那么可能會產生很嚴重的感情矛盾,后果很嚴重。
上面的就是Feed流產品的一些特點,下面我們來看一下Feed流系統的分類。
分類
Feed流的分類有很多種,但最常見的分類有兩種:
- Timeline:按發布的時間順序排序,先發布的先看到,后發布的排列在最頂端,類似於微信朋友圈,微博等。這也是一種最常見的形式。產品如果選擇Timeline類型,那么就是認為
Feed流中的Feed不多,但是每個Feed都很重要,都需要用戶看到
。 - Rank:按某個非時間的因子排序,一般是按照用戶的喜好度排序,用戶最喜歡的排在最前面,次喜歡的排在后面。這種一般假定用戶可能看到的Feed非常多,而用戶花費在這里的時間有限,那么就為用戶選擇出用戶最想看的Top N結果,場景的應用場景有圖片分享、新聞推薦類、商品推薦等。
上面兩種是最典型,也是最常見的分類方式,另外的話,也有其他的分類標准,在其他的分類標准中的話,會多出兩種類型:
- Aggregate:聚合類型,比如好幾個朋友都看了同一場電影,這個就可以聚合為一條Feed:A,B,C看了電影《你的名字》,這種聚合功能比較適合在客戶端做。一般的Aggregate類型是Timeline類型 + 客戶端聚合。
- Notice:通知類型,這種其實已經是功能類型了,通知類型一般用於APP中的各種通知,私信等常見。這種也是Timeline類型,或者是Aggregate類型。
實現
上面介紹了Feed流系統的概念,特征以及分類,接下來開始進入關鍵部分:如何實現一個千萬級Feed流系統。由於系統中的所有用戶不可能全部在線,且不可能同時刷新和發布Feed,那么一個能支撐千萬量級Feed流的系統,其實在產品上可以支撐上億的用戶。
如果要設計一個Feed流系統,最關鍵的兩個核心,一個是存儲,一個是推送。
存儲
我們先來看存儲,Feed流系統中需要存儲的內容分為兩部分,一個是賬號關系(比如關注列表),一種是Feed消息內容。不管是存儲哪一種,都有幾個問題需要考慮:
- 如何能支持100TB,甚至PB級數據量?
- 數據量大了后成本就很關鍵,成本如何能更便宜?
- 如何保證賬號關系和Feed不丟失?
我們后面再解答這三個問題,先繼續看推送
推送
推送系統需要的功能有兩個,一個是發布Feed,一個是讀取Feed流。對於提送系統,仍然有一些問題需要在選型之前考慮:
- 如何才能提供千萬的TPS和QPS?
- 如何保證讀寫延遲在10ms,甚至2ms以下?
- 如何保證Feed的必達性?
再解答這些問題之前,我們先來大概了解下阿里雲的表格存儲TableStore。
TableStore
表格存儲(TableStore)是阿里雲自主研發的專業級分布式NoSQL數據庫,是基於共享存儲的高性能、低成本、易擴展、全托管的半結構化數據存儲平台,
支撐互聯網和物聯網數據的高效計算與分析。
目前不管是阿里巴巴集團內部,還是外部公有雲用戶,都有成千上萬的系統在使用。覆蓋了重吞吐的離線應用,以及重穩定性,性能敏感的在線應用。目前使用的系統中,有些系統每秒寫入行數超過3500萬行
,每秒流量超過5GB
,單表總行數超過10萬億行
,單表數據量超過10PB
。
表格存儲的具體的特性可以看下面這張圖片。
這里就不詳細介紹表格存儲(TableStore)的功能和特性了,有興趣的話可以到官網頁面和雲棲博客了解,地址如下:
- 表格存儲的官網地址:https://www.aliyun.com/product/ots/
- 表格存儲雲棲博客:https://yq.aliyun.com/teams/4/type_blog-cid_22
- 表格存儲釘釘交流群:11789671
存儲系統選擇
我們接下來解決之前提出來的問題。
Feed流系統中需要存儲的系統有兩類,一類是賬號關系(比如關注列表),一類是Feed消息。
存儲賬號關系
我們先來看賬號關系(比如關注列表)的存儲,對於賬號關系,它有一些特點:
- 是一系列的
變長鏈表
,長度可達億級別
。 - 這樣就會導致
數據量比較大
,但是關系極其簡單
。 - 還有一點是性能敏感,直接影響關注,取關的響應速度。
最適合存賬號關系(關注列表)的系統應該是分布式NoSQL數據庫,原因是數據量極大,關系簡單不需要復雜的join,性能要求高。
對內設計實現簡單,對外用戶體驗好。
除了上面這些特點外,還有一個特點:
- 有序性:有序性並不要求具有排序功能,只需要能按照主鍵排序就行,只要能按照主鍵排序,那么關注列表和粉絲列表的順序就是固定的,可預期的。
使用開源HBase存儲賬號關系
能滿足有序性的分布式NoSQL數據庫中,開源HBase就是一個,所以很多企業會選擇開源HBase來存儲賬號關系,或者是關注列表。
這樣雖然滿足了上述四個特征,可以把系統搭建起來,但是會有一些麻煩的問題:
- 需要自己運維,調查問題,Fix bug,會帶來較大的復雜度和成本開支。
- GC會導致比較大的毛刺,影響用戶體驗,
使用表格存儲(TableStore)存儲賬號關系
除此之外,阿里雲的表格存儲也屬於有序性的分布式NoSQL數據庫,之前有不少很有名的系統選擇使用表格存儲,在下面一些地方給系統帶來了收益:
- 單表支持
10萬億行+,10PB+
的數據量,再快的數據增長速度都不用擔心。 - 數據按
主鍵列排序
,保證有序性和可預期性。 - 單key讀寫延遲在
毫秒
級別,保證關注,取關的響應時間。 - 是
全托管
的分布式NoSQL數據庫服務,無需任何運維
。 - 全部
采用C++
實現,徹底無GC問題
,也就不會由於GC而導致較大的毛刺。
使用表格存儲(TableStore)來存儲賬號關系會是一個比較好的選擇。
接下來看一下Feed消息的存儲。
存儲Feed消息
Feed消息有一個最大的特點:
- 數據量大,而且在Feed流系統里面很多時候都會選擇寫擴散(推模式)模式,這時候數據量會再膨脹幾個數量級,所以這里的數據量很容易達到100TB,甚至PB級別。
除此之外,還有一些其他特點:
- 數據格式簡單
- 數據不能丟失,可靠性要求高
- 自增主鍵功能,保證個人發的Feed的消息ID在個人發件箱中都是嚴格遞增的,這樣讀取時只需要一個范圍讀取即可。由於個人發布的Feed並發度很低,這里用時間戳也能滿足基本需求,但是當應用層隊列堵塞,網絡延遲變大或時間回退時,用時間戳還是無法保證嚴格遞增。這里最好是有自增功能。
- 成本越低越好
潛在的存儲系統
根據上述這些特征,最佳的系統應該是具有主鍵自增功能的分布式NoSQL數據庫
,但是在開源系統里面沒有,所以常用的做法有兩種:
- 關系型數據庫 + 分庫分表
- 關系型數據庫 + 分布式NoSQL數據庫:其中 關系型數據庫提供主鍵自增功能。
使用關系型數據庫存儲Feed消息
目前業界有很多用戶選擇了關系系數據庫+ 分庫分表,包括了一些非常著名的Feed流產品,雖然這個架構可以運行起來,但是存在一些問題。
- 分庫分表帶來了
運維復雜性
。 - 分庫分表帶來了邏輯層和數據層的
極大耦合性
。 - 關系型數據庫,比如開源MySQL數據庫的主鍵自增功能性能差。不管是用MyISAM,還是InnoDB引擎,要保證自增ID嚴格遞增,必須使用表鎖,這個粒度非常大,會嚴重限制並發度,影響性能。
- 有些用戶覺得關系型數據庫的可靠性高一些,但是關系型數據庫的可靠性一般也就最多6個9,這個可靠性和分布式數據庫完全不在一個層級,要低4到5個級別。
使用TableStore存儲賬號關系
基於上述原因,一些技術公司開始考慮使用表格存儲(TableStore),表格存儲是一個具有自增主鍵功能的分布式NoSQL數據庫,這樣就只需要使用一種系統,除此之外還有以下的考慮:
- 單表可達10PB,10萬億行。
10個9的SLA保障
Feed內容不丟失。- 天然分布式數據庫,
無需分庫分表
- 兩種實例類型:高性能實例采用全SSD存儲媒介,提供極佳的讀寫性能。混合存儲實例采用SSD+SATA存儲媒介,提供極低的存儲成本。
- 主鍵自增功能性能極佳,其他所有系統在做自增功能的時候都需要加鎖,但是表格存儲的主鍵自增功能在寫入自增列行的時候,完全不需要鎖,既不需要表鎖,也不需要行鎖。
從上面看,使用TableStore的話,不管是在功能,性能,擴展性還是成本方面都要更加適合一些。
看完推送系統選擇后,我們再來看看推送方案的選擇。
推送方案
我們先來回顧下之前說的Feed流系統最大的特點:
- 讀寫嚴重不平衡,讀多寫少,一般讀寫比例都在10;1,甚至100:1之上。
除此之外,還有一個方面會被推送方案影響:
- 發布, 刷新Feed時的延時本質上由
推送方案
決定,其他的任何操作都只能是優化,質量量變,無法質變。
推模式和拉模式對比
在推送方案里面的,有兩種方案,分別是:
- 拉方案:也稱為
讀擴散
。 - 推方案:也成為
寫擴散
。
對於拉方案和推方案,他們在很多方面完全相反,在看對比之前有一點要強調下:
- 對Feed流產品的用戶而言,刷新Feed流(讀取)時候的延遲敏感度要遠遠大於發布(寫入)的時候。
拉模式(讀擴散) | 推模式(寫擴散) | |
---|---|---|
發布 | 個人頁Timeline(發件箱) | 粉絲的關注頁(收件箱) |
閱讀 | 所有關注者的個人頁Timeline | 自己的關注頁Timeline |
網絡最大開銷 | 用戶刷新時 | 發布Feed時 |
讀寫放大 | 放大讀:讀寫比例到1萬:1 | 放大寫減少讀:讀寫比例到50:50 |
個性化 | 不支持 | 支持 |
定向廣告 | 不支持 | 支持 |
推模式的一個副作用
在上面的對比中可以明顯看出來,推模式要遠遠比拉模式更好一些,但是也有一個副作用:
- 數據會極大膨脹。
針對這個缺點,可以從兩個方面考慮:
- 目前的存儲價格很低很低了,就以表格存儲為例,容量型實例存儲10TB的數據量,在現在(2017年10月)每年費用是1萬六千元,以后價格會隨着硬件技術升級,軟件性能優化等繼續降低。還有數據量越大價格越便宜。
-
想省點錢,那繼續可以優化:
- 對大V采用拉模式,普通用戶使用推模式,這種模式有個缺點,后面會有分析。
- 對活躍粉絲采用推模式,非活躍粉絲采用拉模式(這種方式可以較好的避免大流量對平台的沖擊)
適用場景
通過上述兩個方案的對比后,總結下各個方案的適用場景:
-
拉模式:
- 很多Feed流產品的第一版會采用這種方案,但很快就會拋棄。
- 另外,拉模式 + 圖計算 就會是另一番天地,但是這個時候重心就是圖計算了。
-
推模式:
- Feed流系統中最常用、有效的模式;
- 用戶關系數比較均勻,或者有上限,比如朋友圈;
- 偏推薦類,同一個Feed對不同用戶價值不同,需要為不同用戶計算分數,比如pinterest。
-
推拉結合
- 大部分用戶的賬號關系都是幾百個,但是有個別用戶是1000萬以上,比如微博。
上面了解了推送方案,接下來看下推送系統選擇
推送系統
如果要實現一個千萬量級的Feed流產品,那么推送系統需要具備一些特點:
- 具備千萬TPS/QPS的能力。
- 讀寫鏈路延遲敏感,讀寫直接會影響用戶發布,刷新Feed流時的延遲,尤其是極其敏感的刷新時的延遲。
- Feed消息的必達性要求很高。
- 主鍵自增功能,仍然是保證用戶收件箱中的Feed ID是嚴格遞增的,保證可以通過Scan(上次讀取的最大ID --->MAX)讀取到最新未讀消息。
- 最好能為用戶存儲Timeline中所有的Feed。
從上述特點來看,需要的推送系統最好是一個性能極佳,又可靠的有自增功能的NoSQL系統,所以,業內一般如果選擇開源系統的話,會在選擇了關系型數據庫作為存儲系統的基礎上,選擇開源Redis,這樣就能覆蓋上述的幾個特征,也能保證Feed流系統正常運行起來,但是也會帶來一些其他問題:
- 純內存系統,內存價格極高,整體成本就比較高了。
- 屬於單機系統,為了支持千萬TPS和保證消息必達性,需要使用cluster和replica模式,結果就是不僅帶來了運維的復雜性,而且帶來了成本的機器增加,成本再次上升。
-
成本上升了以后,就有架構師開始考慮是否可以節省一些成本,要節省成本只能是減少開源Redis里面存儲的數據量,一般有兩種做法,這兩種做法都能減少存入Redis中的數據量:
- 只在開源Redis中存儲Feed ID,不存儲Feed內容。整體數據量會大量減少,但是在讀取的時候需要先讀Feed ID,然后在到存儲系統里面去讀取Feed內容,網絡開銷增長了一倍,而且是串行的,對用戶的刷新延遲有較大影響。
- 只對普通用戶或者活躍用戶使用推模式,對大V和非活躍用戶直接使用拉模式。
上述兩個方案雖然可以節省成本,但是是以犧牲用戶體驗為代價的,最終需要在成本和用戶體驗之間權衡。
使用TableStore作為推送系統
除了使用開源系統外,還可以使用阿里雲的表格存儲(TableStore),有不少用戶選擇TableStore作為推送系統的原因無非下面幾點:
- 天然分布式,單表可支持千萬級TPS/QPS。
- LSM存儲引擎極大
優化寫
,高性能實例極大優化讀
。 - 寫入成功即保證落盤成功,數據可靠性提供10個9的SLA保障。
- 磁盤性數據庫,費用比內存性的要低幾個量級。
- 單表可存儲十萬億行以上的數據,價格又低,輕松保存用戶Feed流中的所有Feed數據。
上面說了使用開源Redis和阿里雲TableStore的異同,如果使用開源可以用Redis,如果選擇阿里雲自研NoSQL數據庫,可以使用TableStore。
架構圖
下面我們來看一下使用TableStore的架構圖,這里為了通用性,選用推拉結合的方式,推模式更加簡單。
存儲
我們先來看中間黑色框中的部分,這部分是使用TableStore的數據,從左往右分別是:
- 個人頁Timeline:這個是每個用戶的發件箱,也就是自己的個人頁頁面。
- 關注頁Timeline:這個是每個用戶的收件箱,也就是自己的關注頁頁面,內容都是自己關注人發布的消息。
- 關注列表:保存賬號關系,比如朋友圈中的好友關系;微博中的關注列表等。
- 虛擬關注列表:這個主要用來個性化和廣告。
發布Feed流程
當你發布一條Feed消息的時候,流程是這樣的:
- Feed消息先進入一個隊列服務。
- 先從關注列表中讀取到自己的粉絲列表,以及判斷自己是否是大V。
- 將自己的Feed消息寫入個人頁Timeline(發件箱)。如果是大V,寫入流程到此就結束了。
- 如果是普通用戶,還需要將自己的Feed消息寫給自己的粉絲,如果有100個粉絲,那么就要寫給100個用戶,包括Feed內容和Feed ID。
- 第三步和第四步可以合並在一起,使用BatchWriteRow接口一次性將多行數據寫入TableStore。
- 發布Feed的流程到此結束。
讀取Feed流流程
當刷新自己的Feed流的時候,流程是這樣的:
- 先去讀取自己關注的大V列表
- 去讀取自己的收件箱,只需要一個GetRange讀取一個范圍即可,范圍起始位置是上次讀取到的最新Feed的ID,結束位置可以使當前時間,也可以是MAX,建議是MAX值。由於之前使用了主鍵自增功能,所以這里可以使用GetRange讀取。
- 如果有關注的大V,則再次並發讀取每一個大V的發件箱,如果關注了10個大V,那么則需要10次訪問。
- 合並2和3步的結果,然后按時間排序,返回給用戶。
至此,使用推拉結合方式的發布,讀取Feed流的流程都結束了。
更簡單的推模式
如果只是用推模式了,則會更加簡單:
-
發布Feed:
- 不用區分是否大V,所有用戶的流程都一樣,都是三步。
-
讀取Feed流:
- 不需要第一步,也不需要第三步,只需要第二步即可,將之前的2 + N(N是關注的大V個數) 次網絡開銷減少為 1 次網絡開銷。讀取延時大幅降級。
個性化和定向廣告
個性化和定向廣告是兩種很強烈的產品需求。個性化可以服務好用戶,增大產品競爭力和用戶粘性,而定向廣告可以為產品增加盈利渠道,而且還可以不招來用戶反感,那么這兩種方式如何實現呢? 在Feeds流里面這兩種功能的實現方式差不多,我們以定向廣告為例來說明:
- 通過用戶特征分析對用戶分類,比如其中有一類是新生類:今年剛上大學的新生。(具體的用戶特征分析可以依靠TableStore + MaxCompute,這里就不說了)。
- 創建一個廣告賬號:新生廣告
- 讓這些具有新生特征的用戶虛擬關注新生廣告賬號。用戶看不到這一層關注關系。
- 從七月份開始就可以通過新生廣告賬號發送廣告了。
- 最終,每個用戶可能會有多個特征,那么就可能虛擬關注多個廣告賬號。
上面是定向廣告的一種比較簡單的實現方式,其他方式就不再贅述了。
收益
上面我們詳細說了使用TableStore作為存儲和推送系統的架構,接下來我們看看新架構能給我們帶來多大收益。
- 只使用1種系統,架構、實現簡單。不再需要訪問多個系統,架構,開發,測試,運維都能節省大力人力時間。
- TableStore 主鍵自增列功能性能極優。由於架構的不同,不僅不需要表鎖,行鎖也不需要,所以性能要遠遠好於關系型數據庫。
- 可以保存所有的Feed。一是系統可以支持存儲所有Feed,二是價格便宜,存的起。
- 無須將Feed ID和內容分開存儲。價格便宜,也就不需要再分開存儲ID和內容了。
- 全托管服務,無運維操作,更無需分庫分表。
- 磁盤型(SSD、Hybrid)數據庫,成本低。
- 可靠性10個9,數據更可靠,更不易丟失。
- 大V和普通用戶的切分閾值更高,讀取大V的次數更少,整體延時更低。
一個設計缺陷
如果使用大V/普通用戶的切分方式,大V使用拉模式,普通用戶使用推模式,那么這種架構就會存在一種很大的風險。
比如某個大V突然發了一個很有話題性的Feed,那么就有可能導致整個Feed產品中的所有用戶都沒法讀取新內容了,原因是這樣的:
- 大V發送Feed消息。
- 大V,使用拉模式。
- 大V的活躍粉絲(用戶群A)開始通過拉模式(架構圖中讀取的步驟3,簡稱讀3)讀取大V的新Feed。
- Feed內容太有話題性了,快速傳播。
- 未登錄的大V粉絲(用戶群B)開始登陸產品,登陸進去后自動刷新,再次通過讀3步驟讀取大V的Feed內容。
- 非粉絲(用戶群C)去大V的個人頁Timeline里面去圍觀,再次需要讀取大V個人的Timeline,同讀3.
結果就是,平時正常流量只有用戶群A
,結果現在卻是用戶群A + 用戶群B+ 用戶群C
,流量增加了好幾倍,甚至幾十倍,導致讀3路徑的服務模塊被打到server busy或者機器資源被打滿,導致讀取大V的讀3路徑無法返回請求,如果Feed產品中的用戶都有關注大V,那么基本上所有用戶都會卡死在讀取大V的讀3路徑上,然后就沒法刷新了。
所以這里設計的時候就需要重點關心下面兩點:
- 單個模塊的不可用,不應該阻止整個關鍵的讀Feed流路徑,如果大V的無法讀取,但是普通用戶的要能返回,等服務恢復后,再補齊大V的內容即可。
- 當模塊無法承受這么大流量的時候,模塊不應該完全不可服務,而應該能繼續提供最大的服務能力,超過的拒絕掉。
那么如何優化呢?
- 不使用大V/普通用戶的優化方式,使用活躍用戶/非活躍用戶的優化方式。這樣的話,就能把用戶群A和部分用戶群B分流到其他更分散的多個路徑上去。而且,就算讀3路徑不可用,仍然對活躍用戶無任何影響。
- 完全使用推模式就可以徹底解決這個問題,但是會帶來存儲量增大,大V微博發送總時間增大,從發給第一個粉絲到發給最后一個粉絲可能要幾分鍾時間(一億粉絲,100萬行每秒,需要100秒),還要為最大並發預留好資源,如果使用表格存儲,因為是雲服務,則不需要考慮預留最大額度資源的問題。
實踐
接下來我們來實現一個消息廣場的功能。很多App中都有動態或消息廣場的功能,在消息廣場中一般有兩個Tab,一個是關注人,一個是廣場,我們這里重點來看關注人。
要實現的功能如下:
- 用戶之間可以相互關注
- 用戶可以發布新消息
- 用戶可以查看自己發布的消息列表
- 用戶可以查看自己關注的人的消息
采取前面的方案:
- 使用TableStore作為存儲和推送系統
- 采用Timeline的顯示方式,希望用戶可以認真看每條Feed
- 采用推模式
角色
接着,我們看看角色和每個角色需要的功能:
-
發送者
- 發送狀態:add_activity()
-
接收者
- 關注:follow()
- 讀取Feed流:get_activity()
Feed消息中至少需要包括下面內容:
-
消息:
- 發送人:actor
- 類型:verb,比如圖片,視頻,文本
- 文本文字:message
架構圖
-
發布新消息
- 接口:add_activity()
-
實現:
- get_range接口調用關注列表,返回粉絲列表。
- batch_write_row接口將feed內容和ID批量寫入個人頁表(發件箱)和所有粉絲的關注頁表(收件箱),如果量太大,可以多次寫入。或者調用異步batch_write_row接口,目前C++ SDK和JAVA SDK提供異步接口。
-
關注
- 接口:follow()
-
實現:
- put_row接口直接寫入一行數據(關注人,粉絲)到關注列表和粉絲列表(粉絲,關注人)即可。
-
獲取Feed流消息
- 接口:get_activity()
-
實現:
- 從客戶端獲取上次讀取到的最新消息的ID:last_id
- 使用get_range接口讀取最新的消息,起始位置是last_id,結束位置是MAX。
- 如果是讀取個人頁的內容,訪問個人頁表即可。如果是讀取關注頁的內容,訪問關注頁表即可。
計划
上面展示了如何使用表格存儲TableStore的API來實現。這個雖然只用到幾個接口,但是仍然需要學習表格存儲的API和特性,還是有點費時間。
為了更加易用性,我們接下來會提供Feeds流完整解決方案,提供一個LIB,接口直接是add_activity(),follow()和get_activity()類似的接口,使用上會更加簡單和快捷。
擴展
前面講述的都是Timeline類型的Feed流類型,但是還有一種Feed流類型比較常見,那就是新聞推薦,圖片分享網站常用的Rank類型。
我們再來回顧下Rank類型擅長的領域:
- 潛在Feed內容非常多,用戶無法全部看完,也不需要全部看完,那么需要為用戶選出她最想看的內容,典型的就是圖片分享網站,新聞推薦網站等。
我們先來看一種架構圖:
- 這種Rank方式比較輕量級,適用於推拉結合的場景。
- 寫流程基本一樣
- 讀流程里面會先讀取所有的Feed內容,這個和Timeline也一樣,Timeline里面的話,這里會直接返回給用戶,但是Rank類型需要在一個排序模塊里面,按照某個屬性值排序,然后將所有結果存入一個timeline cache中,並返回分數最高的N個結果,下次讀取的時候再返回[N+1, 2N]的結果。
再來看另外一種:
- 這種比較重量級,適用於純推模式。
- 寫流程也和Timeline一樣。
-
每個用戶有兩個收件箱:
- 一個是關注頁Timeline,保存原始的Feed內容,用戶無法直接查看這個收件箱。
- 一個是rank timeline,保存為用戶精選的Feed內容,用戶直接查看這個收件箱。
- 寫流程結束后還有一個數據處理的流程。個性化排序系統從原始Feed收件箱中獲取到新的Feed 內容,按照用戶的特征,Feed的特征計算出一個分數,每個Feed在不同用戶的Timeline中可能分數不一樣的,計算完成后再排序然后寫入最終的rank timeline。
- 這種方式可以真正為每個用戶做到“千人千面”。
上述兩種方式是實現Rank的比較簡單,常用的方式。
最后
從上面的內容來看,表格存儲(TableStore)在存儲方面可以支持10PB級,推送方面可以支撐每秒千萬的TPS/QPS,在Feed流系統中可以發揮很大的價值。
目前,已經有不少著名公司在使用表格存儲(TableStore)來構建他們自己的Feed流系統,最終為系統,產品,公司都帶來了不少收益。