從 0 開始設計 Twitter 系統架構
Twitter 是全球最大的社交網絡之一,如果讓我們從 0 開始設計 Twitter 的系統架構,該怎麼做呢?有哪些服務是必須的?有哪些點需要提前考慮?這篇文章簡單介紹了設計類 Twitter 系統的思路並在最後給出了參考設計。原文鏈接:https://medium.com/interviewnoodle/twitter-system-architecture-8dafce16aec4
Twitter 是全球領先的在線社交網絡服務,用戶可以在這裏發佈和閱讀被稱爲 “推文(tweets)” 的短消息。在系統架構設計面試過程中,當被問及如何設計 Twitter 時,大多數候選人都會將其設計爲單體服務。然而,將 Twitter 這樣的大型服務設計爲單體,表明候選人缺乏設計分佈式系統的經驗。從微服務甚至 lambda(或函數)的角度來設計分佈式系統在今天是很正常的選擇。目前的趨勢是,沒有人會將新服務設計爲單體,公司正逐漸將其龐大的單體服務轉換爲一組微服務。因此,候選人應該以微服務的方式設計 Twitter。
功能需求
-
用戶可以發佈或分享新的推文(tweet)
-
每條推文最多不超過 140 個字符
-
用戶可以刪除推文,但不能更新 / 編輯發佈的推文(寫操作)
-
用戶可以標記喜歡的推文(寫操作)
-
用戶可以關注或取消關注另一個用戶(寫操作),關注一個用戶意味着用戶可以看到其他用戶在他的時間線上的推文
-
可以生成兩種類型的時間線(讀操作),用戶時間線由他最後 N 個推文組成,主頁時間線由他正在關注的用戶的熱門推文按照時間降序生成
-
用戶可以根據關鍵字搜索推文(讀操作)
-
用戶需要有一個帳戶來發布或讀取推文(暫時使用外部身份服務)
-
用戶可以註冊和刪除帳戶
-
Twitter 支持包含文字和圖片 / 視頻的推文,但在我們當前的設計中,將只支持文本
-
分析 / 監視服務,以確定其負載、運行狀況和功能
-
分析還可爲用戶提供關於關注誰、推文通知、熱門話題、推送通知和分享推文的意見或建議
非功能需求
-
服務的高可用是最重要的需求,這意味着用戶可以在自己的主頁時間線上閱讀推文,而感受不到任何停頓
-
生成時間線的時間最長不得超過半秒
-
不需要強一致性,只需要最終一致性,可以使用關鍵詞數據庫用於搜索基於關鍵詞的推文
-
隨着用戶和推文的增加,系統負載也在增加,因此係統應該具有可伸縮性
-
持久化用戶數據
現在我們來做一些計算:
-
日活躍用戶平均請求 / 天 = 150M*60/86400 = 100k / 秒
-
峯值用戶 = 平均併發用戶 * 3 = 300k
-
三月內最大峯值用戶數 = 峯值用戶數 * 2 = 600k
-
讀 QPS = 300k
-
寫 QPS = 5k
Twitter 服務的概要設計
由於系統的複雜性,可以將其劃分爲若干個服務,其中包括若干個微服務。
-
推文服務(Tweet service)
-
用戶時間線服務(User timeline service)
-
扇出服務(Fanout Service)
-
主頁時間線服務(Home timeline service)
-
社交網絡服務(Social graph service)
-
搜索服務(Search service)
下面是 Twitter 服務中不同邏輯組件或微服務架構。
Twitter 服務的詳細設計
所有微服務都可以被稱爲模塊。
推文服務(Tweet service)
-
接收用戶推文,轉發用戶推文到關注者時間線和搜索服務
-
存儲用戶信息,推文信息,包括用戶的推文數量以及用戶喜歡的狀態
-
包括應用服務器、分佈式的內存緩存以及後端的分佈式數據庫,或者使用直接由數據庫(例如 Redis)支持的內存緩存
然後我們看一下 Tweet 服務的數據庫表結構。
用戶(Users)表包含用戶的所有信息,推文(Tweet)表存儲所有推文,Favorite_tweet 表存儲了喜歡的推文記錄,也就是說,每當用戶喜歡一條推文時,就會在 Favorite_tweet 表中插入一條記錄。
生成唯一的推文 ID
當用戶調用 postTweet() 時,調用會發送給應用服務器。應用服務器爲該推文生成一個唯一的 id,同樣的機制也可以用來爲推文生成短 URL。另一個方式是基於應用服務器的 UUID(Universally unique identifier)。推文 ID 生成後,應用服務器將該推文插入分佈式緩存和數據庫的 tweet 表中。由於需要在執行推文的創建 / 更新 / 刪除操作的同時更新緩存和數據庫,所以我們使用緩存透寫機制。
可擴展性設計
我們可以將分佈式緩存和數據庫劃分爲多個分區和副本。
-
基於用戶 ID 分片
-
基於推文 ID 分片
-
基於用戶 ID 和推文 ID 進行兩層 / 級別分片
社交網絡服務(Social graph service)
-
實現 Following API,跟蹤用戶之間的關注關係
-
包括應用服務器、分佈式緩存和數據庫
-
用於存儲用戶關係的數據庫表結構
Following API:
-
將被關注用戶的時間線異步合併到關注者的信息事件流中
-
取消關注一個用戶後,從關注者的事件流中異步刪除他的推文
-
異步的從信息事件流中挑選推文
-
之所以需要異步操作,是因爲這個過程比較慢,而用戶在關注和取消關注其他用戶時,希望很快得到反饋
-
異步的缺點是用戶在取消關注後,如果刷新信息事件流,會發現這些信息仍然存在,但最終它們會被刪除
用戶時間線服務(User timeline service)
-
返回用戶的時間線,以降序排列的方式包含用戶所有推文。此服務可用於主頁時間線或其他用戶的時間線。
-
該服務包括應用服務器和分佈式內存緩存,但沒有涉及該服務的數據庫。
-
用戶時間線是使用包含用戶推文鏈接列表的數據結構設計的。
-
當用戶發佈一條推文時,tweet 服務調用用戶時間線服務,將該推文插入到用戶時間線的推文列表頂部,運算複雜度爲 O(1)。
-
此外,分析儀表板可以配置參數 K,表示可以保留的推文個數,K 默認爲 1000,表示保留用戶時間線軸中的最後 K 條推文。
-
在用戶時間線列表中,推文按 creationTime(創建時間)降序存儲。當用戶時間線列表達到最大 K 條推文時,最老的條目將被刪除。
扇出服務(Fanout Service)
-
將新推文轉發到搜索和主頁時間線服務,以及其他組件 / 微服務,比如趨勢服務或通知服務
-
由多個分佈式隊列組成
-
當用戶發送一條推文消息時,該服務把消息放入推文隊列,社交網絡服務必須獲得用戶的關注者列表,並在第二組隊列中插入儘可能多的消息。對於名人用戶來說,他們擁有非常多的粉絲,其粉絲數甚至超過了每次推送的閾值。那麼,如何處理這個問題呢?
-
該服務是一個先進先出的任務隊列列表,處理共享相同列表的任務,並在完成後反饋給隊列服務器。隊列服務器是異步任務的重要組成部分,其執行的任務可能不會立即收到響應,但卻能夠保證最終一致性。
主頁時間線服務(Home timeline service)
-
顯示用戶的主頁時間線
-
包括來自其他關注的用戶的推文,按照推文的 creationTime(創建時間)降序顯示。
-
其設計類似於用戶時間線服務。
-
但是比用戶時間線服務稍微複雜一點,因爲用戶將插入最新的推文,並且當推文數量超過 K 值時需要刪除最老的推文,如果用戶關注了很多其他用戶,服務還需要一些機制來給不同關注用戶的推文賦予不同的權重。
搜索服務(Search service)
-
爲用戶提供搜索查詢服務
-
扇出服務將推文傳遞給搜索服務
-
Ingester(或 ingestion engine):給推文標記上許多標籤、術語或關鍵字。例如這條推文:“我想成爲像亞馬遜的傑夫 · 貝索斯一樣非常富有的人”,它會過濾掉那些在搜索中沒有用的詞。除了傑夫 · 貝索斯(Jeff Bezos)和亞馬遜(Amazon),所有其他詞都將被丟棄。Ingester 可以通過配置或數據庫獲得詞彙表。
-
一個叫做 “詞根提取(stemming)” 的過程對剩下的單詞進行分析,以確定它們的詞根。Stemming 是處理詞幹、詞根或詞根的詞形變化 (或派生) 的過程。因此,會在數據庫中保存一個查找表。這種方法的優點是可以簡單、快速、輕鬆的處理異常。缺點是新的或不熟悉的單詞即使是完全符合規則的,也不會被處理。
-
傳遞到搜索索引
-
搜索索引微服務將創建反向索引,並存儲從內容(如單詞)到其所在文檔或一組文檔中的位置的術語映射索引,在我們的例子中,這是一個或一組推文。
-
Blender 服務:在 Twitter 平臺上爲用戶提供搜索查詢。當請求搜索查詢時,首先確定搜索條件,然後進行詞幹分析,最後使用詞根在術語的倒排索引上運行搜索查詢。
照片和視頻
-
使用 NoSQL 數據庫
-
媒體文件(使用文件系統)
-
數據表格式
Twitter 的網絡
Twitter 的最終詳細設計
系統設計:
數據架構:
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/16d_aamO9FFRPtwrxcb1HA