天天看點

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

摘要:

阿裡巴巴進階技術專家木洛在2018雲栖大會·深圳峰會中就Feed流的概念介紹、概念架構以及TableStore場景的Timeline模型等方面的内容做了深入的分析。本文帶領大家一起了解并學習如何通過存儲系統的性能特性,通過Feed流中的消息存儲和推送機制支撐起千萬Feed流的并發。

數十款阿裡雲産品限時折扣中,

趕緊點選這裡

,領劵開始雲上實踐吧!

以下内容根據演講嘉賓PPT以及視訊整理而成(雲栖社群做了不修改原意的編輯)。

本次的分享主要圍繞以下三個方面:

一、概念介紹

二、Feed流系統架構

三、TableStore Timeline

下圖為比較抽象的Feed流系統,系統被分為Feed,Feed流以及Feed訂閱三個層次。Feed可以看作消息體,消息體就像我們發送的資訊,平時釋出的動态,新聞App中的一條新聞,或者推薦的内容,我們将這些統稱為Feed。Feed産生之後,通過Feed流被推送到Feed訂閱端,這個過程就是典型的Feed三層系統。Feed是一種實時消息,由于消息是實時産生,實時消費,實時推送的,是以滿足實時性是關鍵。另外消息來自于很多不同的消息源,消息的産生屬于海量級别。Feed流是實時推送的有序的可擴散的消息流,Feed産生之後,我們通常會将這些Feed推送給Feed的訂閱端,推送的過程中需要滿足有序,可擴散的原則。消息順序有時間線類型,即按照消息産生的時間對消息進行排序;也有Rank類型,這種類型主要出現在推薦資訊中,根據某些算法或消息所處的類别找到最相關的訂閱端。一個消息可能是由單個消息體産生的,而這個消息體可以擴散到很多的訂閱端,從消息産生到消息消費産生巨大的讀寫比。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

下圖展示了常見的Feed應用,朋友圈中的Feed就是每個人釋出的動态,動态通過朋友圈的Feed流擴散到好友,同時每個人也可以在朋友圈中訂閱到好友釋出的動态。微網誌也是較為常見的Feed應用。Pinterest是國外關于圖檔的社交系統,與其它Feed系統不同的是,Pinterest的Feed就是圖檔。雪球的動态廣場是一個讨論組,大家可以在讨論組裡釋出消息,讨論組的人也可以訂閱組内消息。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密
二、Feed流系統架構

下面為大家舉例介紹主要Feed流整體架構的實作。在講架構實作的時候,本文會先介紹一個簡單且為大家所熟知的案例。如下圖所示,朋友圈是大家常用的社交平台,首先定義某個功能實作需要滿足什麼需求。第一點是朋友圈中的動态:在消息發送方面,消息會存到個人相冊,每個人能在個人相冊中看到自己釋出的所有動态,并且這些動态是永久儲存的,我們可以翻到N多年前自己釋出的消息,是以這些消息有一個很長時間的儲存狀态;另外消息會擴散到好友的朋友圈,消息儲存在持有好友關系的朋友圈;同時我們的朋友圈也儲存着好友發的動态,作為消息儲存。朋友圈中不僅僅隻有釋出的動态,也可能有一些廣告,這些廣告是由廣告系統推薦過來的。以上是朋友圈簡單的Feed流功能需求分析。總結功能需求如下圖中所示:

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

人與人之間組建好友關系,朋友圈用于檢視好友圈内的人發送的所有消息,按照動态釋出的時間進行時間排序;廣告系統可向朋友圈内插入廣告消息,這是一個rank的消息;個人相冊用于檢視個人發送的所有消息。并且,個人相冊和朋友圈是有所差別的,個人相冊中需要永久儲存個人釋出的動态,但是朋友圈可以隻看最近一段時間的消息,這點在我們之後設計消息系統時,會有所差別。

針對上文所說的朋友圈場景,下文為大家介紹一個簡單的Feed流系統架構大概會分為哪幾個子產品。如下圖所示,首先會設計一個端,用來發送消息或者接收消息,這就是消息的入口。其次,會有接入層,我們通常把它叫做消息伺服器,這些消息伺服器通常是由一組無狀态的伺服器組成的,主要職能是接收消息,處理消息以及當端讀消息時的同步消息。接入層算是比較簡單的實作,通常都是一些API網關,提供特定消息處理的API,并且涉及到消息協定中的特定實作,包括資料加密,優化的通信等。最核心的是背景服務,如下圖所示,把背景服務簡單化為兩塊,第一塊是消息系統,消息系統是整個Feed流架構中最核心的部分,負責對消息進行持久化,個人的消息會先持久化都自己的庫中;其次負責對消息進行同步,将消息同步給自己的好友或者抽取某些好友訂閱自己的消息。廣告系統會找到和廣告最關聯的人群,向這些人推送消息。消息系統下面最核心的是兩個庫的設計,一個是消息存儲庫,另外一個是消息同步庫。這兩個庫的差別在于,消息存儲庫往往是用于永久存儲所有人釋出的所有消息;消息同步用來将一條消息向該同步的人同步。因為廣告系統需要将廣告推動給關聯的人群,是以廣告系統會和消息同步庫打交道,同時,由于廣告是不需要永久存儲的,是以不需要和消息存儲打交道。下圖中最核心的是消息系統的設計,它的設計與實作和Feed流中的消息發送,訂閱以及特征非常相關。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

接下來我們看一下,當我們設計一個消息系統時,一定要足夠了解系統的場景,了解在這個場景裡面,這個消息系統需要滿足什麼要求。

如下圖所示,将要求歸為三:

類,第一類我們需要了解Feed流系統中消息的特征是什麼:第一個特征是典型的讀多寫少,讀多寫少的含義就是我們在朋友圈中通常是讀動态,很少人去發消息,讀寫比大概為100:1;第二個消息模型比較簡單,就是消息體,或者消息,消息裡面可能會有發送人,接收人,消息時間等屬性。在消息确定時模型中的資料已經确定了,而且消息與消息之間是沒有關聯的;第三個是弱關系型資料,就是消息不會和其他資料産生關聯,隻是流式産生的一條條消息;第四個是波峰波谷式通路,指消息系統承載的流量呈現出波峰波谷式通路的特征,因為Feed流系統通常屬于社交類系統,社交系統的活躍度取決于人群的活躍度,人群的活躍度會有很明顯的波峰波谷。上述四種特征對于我們以後設計消息系統時選擇消息存儲的資料庫是至關重要的,也具有參考意義。

第二類是關于消息存儲,個人相冊是需要永久存儲的,存儲量随着時間的推移會越來越大。因為消息的讀寫是線上的,不可能用一個本地存儲,是以消息存儲要求擁有線上永久存儲的能力。同時,朋友圈中的動态需要保證高可靠性,不能輕易丢失。當應用達到很大的使用者量時存儲的消息容量會很巨大,處在PB級,屬于萬億行的規模。

第三類關于消息同步,消息的産生與推送都對消息庫産生很大的壓力,需要能夠應對海量消息;需要實作實時同步,多端同步;同步模型包括寫擴散和讀擴散。下面舉一個例子了解一下寫擴散和讀擴散。一個人有100個好友,他在朋友圈中釋出了一條動态,動态是如何同步到100個好友的朋友圈的呢?解決方案有兩種,第一,每個人都有一個收件箱,向每個人的收件箱中投遞一個消息。這種方案的好處在于,因為每個人都有一個收件箱,所有我們隻需要檢視收件箱,就可以看到别人給我傳遞的消息,對讀有很大的優化,相對而言缺點是消息的寫操作是需要擴散的,擴散的比例就是好友的個數,以上是寫擴散的優劣。第二,采用讀擴散,讀擴散的好處在于資料隻需要寫一份,比如說将消息存儲在我們自己的庫中就行了,壞處是當我們需要拉取新的消息時,假設要擷取100個好友的新資訊,我們就需要從100個人那邊拉取新消息,這對系統産生較大的讀壓力。以上是寫擴散和讀擴散的主要差別。

實際上,Feed流系統讀寫比例是100:1,讀操作是非常多的,在這種資料特征下,如果我們繼續采用讀擴散,将會把讀寫比拉的更大,有可能将100:1拉到1000:1,這會導緻在設計消息系統容量時,取讀或者寫的最高上限,上限拉高之後,對系統要求的能力也會變高,對系統的成本要求也越高。這時,如果采用寫擴散,将把寫的比例拉高,使讀寫比取得均衡,對系統的預留資源要,是以在Feed流系統中通常采用寫擴散這個模式。但是,寫擴散有一個缺點,寫會擴散很多份,當朋友圈中有1萬個好友,寫擴散缺點會很明顯,是以可以采用混合模式進行優化,例如大部分消息采用寫擴散,對于擴散比例很高的消息可以采用讀擴散。有一個優化方式,

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

在了解了消息的特征,存儲和同步後,我們接下來就要選擇合适的資料庫,下圖展示了NoSQL的解決方案。NoSQL的解決方案關注容量,服務能力,分布式支援,售賣模式以及資料模型。在容量方面,傳統關系型資料庫的容量在TB級别,而NoSQL采用分布式,是以容量在10PB級别。服務能力方面,十萬TPS對應于千萬TPS。分布式支援方面,對于這樣海量資料的系統來說,必須采用分布式,在圖中,分庫分表對原生支援。售賣模式方面,按規格計費對按量計費,由于Feed流系統是一個具有波峰波谷式特征的系統,按量模式的售賣模式能幫助節約很多成本。資料模型方面,關系型對弱關系型,弱關系型在Feed流系統下也是滿足需求的。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

TableStore為了簡化Feed流系統的開發,之後就推出了TableStore Timeline。下圖是Timeline簡單邏輯模型。如下圖所示,消息會有一個發送端(A),消息會有訂閱端(B1,B2,B3),消息同步通過隊列,是一個虛拟的隊列,消息需要同步給誰,就将消息發到隊列中。隊列提供的功能有以下幾個:

每個消息都有一個順序ID,用來完成消息的同步,由于每個接收端同步的速度是不同的,每個接收端會保留自己的同步位點,在進行消息同步時,隻需要通過同步位點,到消息清單中随機定位,定位之後拉取所有需要同步的消息,這是一個簡單的模型。對于每個人的收件箱以及發件箱,都是一個獨立的Timeline,在底層資料庫中存儲的内容就變成了每個人的收件箱以及發件箱,如果有1000萬的使用者,資料庫中就需要存儲1000萬的timeline,在這種情況下,資料庫就要達到千億萬億的規模。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

下面我們一起看下,基于Timeline的消息系統的架構實作,如下圖所示。圖中有幾條關鍵路徑,首先是消息的寫操作,消息是如何寫的,寫完如何做同步。;第二個是消息的讀。對于消息的寫,首先端上發送一個消息到消息伺服器;通常消息伺服器為了異步化批量處理消息,都會将消息寫進消息隊列;消息隊列中的消息會進行專門的消息處理;每個消息上傳到伺服器之後,将消息存儲到個人相冊中,個人相冊存儲在消息存儲庫中,其中存儲着每個人的timeline,每個人讀自己對應的timeline就可以讀取自己的動态;在存儲timeline之後,需要将消息同步到自己所有的好友,采取寫擴散的消息同步模型;最後,標明所有的好友,将自己的消息發送到所有好友的收件箱,是以消息同步庫中存儲的是所有好友的收件箱。同步消息通常會看兩個地方,一個是個人相冊,從消息存儲庫中根據同步位點拉取内容。同時,我們隻需要從消息同步庫中拉取自己的收件箱,就可以看到還有發送的所有消息。消息存儲庫與消息同步庫有不同的要求,消息存儲庫要求PB級資料低成本永久存儲,消息同步庫需要提供高并發及低延遲讀,另外,需要存儲每個使用者的收件箱資料,資料生命周期為半年。TableStore提供的功能為容量型提供低成本存儲,高性能提供低延遲讀,以及PB級存儲,毫秒級延遲。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

下圖展示了Timeline性能的實驗分析結果,可以看到在同步100萬擴散寫時,比如說我将消息發給100萬個人,在8核機器上,隻需要3.7s的時間。在16核機器上,并發讀取資料能達到4萬QPS。

朋友圈不知你看到的那麼簡單,千萬Feed流系統的存儲技術解密

本文由雲栖志願小組沈金鳳整理,編輯百見