在過去的二十年裡,大規模在線應用程序取得了長足的進步。 這些創新改變了我們對軟件開發的看法。 例如,Facebook、Instagram 和 Twitter 都是可擴展的平台。
這些系統必須能夠管理大量流量和數據,因為全世界有數十億人同時使用它們。 這是當 系統設計 進入圖片。
為滿足特定標準的系統建立體系結構、接口和數據的過程稱為系統設計。 通過具有凝聚力和高效的系統,系統設計可以滿足您的企業或組織的需求。
一旦您的公司或組織確定了其標準,您就可以開始將它們納入滿足消費者需求的物理系統設計中。
無論您選擇定制開發、商業解決方案還是兩者的組合,您設計系統的方式將決定您如何構建它。
我們將在這篇文章中詳細介紹 Twitter 時間軸的系統設計,並附上教程。 讓我們開始吧。
第 1 步:概述用例和約束
用例
- 用戶上傳一條推文。
- 該服務向推文的關注者發送推送通知和電子郵件。
- 查看用戶的時間線(用戶的活動)
- 用戶查看主頁時間線(用戶關注的人的活動)
- 關鍵詞由用戶搜索。
- 服務真的很貼心。
超出範圍
- 使用此服務將推文發送到 Twitter Firehose 和其他流。
- 該服務根據用戶的可見性設置刪除推文。
- 如果用戶沒有關注被回复的人,則隱藏回复。
- 觀察“隱藏轉發”選項。
- 分析(Analytics)
約束和假設
狀態假設
- 交通分佈不均勻。
- 發送推文應該很簡單。
- 除非您有數百萬關注者,否則向所有關注者發送推文應該很快。
- 有100億活躍用戶。
- 每月 15 億條推文或每天 500 億條推文
- 每條推文的平均扇出數為 10 次。
- 每天,fanout 都會發布 5 億條推文。
- Fanout 每月發布 150 億條推文。
- 每月 250 億次讀取請求
- 每月 10 億次搜索
時間線
- 時間線應該易於瀏覽。
- Twitter更多的是閱讀而不是寫作。
- 優化推文快速閱讀
- 推文消費非常耗時。
檢索
- 搜索過程應該很快。
- 尋找起來很費時間。
計算用量
每條推文的大小:
- 8 字節推文 ID
- 32字節用戶ID
- 140 字節文本
- 媒體 – 平均 10 KB
- 總計:~10 KB
每個月都會生成 150 TB 的新鮮推文內容。
- * 每天 500 億條推文 * 每月 30 天 * 每條推文 10 KB
- 三年內,新鮮推文內容達到 5.4 PB。
每秒有 100,000 個讀取請求。
- *(每秒 400 個請求/每月 1 億個請求)每月 250 億個讀取請求
每秒有 6,000 條推文。
- *(每秒 400 個請求/每月 1 億個請求)每月 15 億條推文
在扇出方面,每秒發送 60 萬條推文。
- Fanout 每月發送 150 億條推文*(每秒 400 個請求/每月 1 億個請求)。
每秒 4,000 個信息請求
- *(每秒 400 個請求/每月 1 億個請求)每月 10 億次搜索
一些有用的轉換
- 每個月,2.5 萬秒過去了。
- 每月 2.5 萬個請求,每秒 1 個請求
- 每月 100 億個請求 x 每秒 40 個請求
- 每月 1 億個請求 = 每秒 400 個請求
第 2 步:高級圖
第三步:解釋核心組件
如果用戶提交推文,我們可以保存用戶自己的推文,以將用戶時間線(用戶的活動)填充到關係數據庫中。 發送推文和開發主頁時間線(用戶關注的個人的活動)更加困難。
典型的關係數據庫會因向所有關注者散佈推文(每秒發送 60 萬條推文)而不堪重負。 我們可能想要使用快速寫入的數據存儲,例如 NoSQL 數據庫或內存緩存。
從內存中順序讀取 1 MB 大約需要 250 微秒,但從 SSD 讀取需要花費 4 倍的時間,從磁盤讀取需要花費 80 倍的時間。
對象存儲可用於存儲圖像和視頻等數據。
- 充當反向代理的 Web 服務器接收來自客戶端的推文。
- 請求由 Web Server 發送到 Write API 服務器。
- Write API 將推文保存到用戶時間線中的 SQL 數據庫中。
扇出服務由 Write API 聯繫,並執行以下任務。
- 通過查詢用戶圖形服務在內存緩存中查找用戶的關注者。
- 在內存緩存上,推文保存在用戶關注者的主頁時間線中。
- 1,000 個關注者 = 1,000 次查找和插入 = O(n) 操作。
- 該推文保存在搜索索引服務中,以便快速搜索。
- 對象存儲用於存儲媒體。
- 通過通知服務向關注者發送推送警報。
- 為了異步發送警報,它使用隊列。
如果我們的內存緩存是 Redis,我們可以使用具有以下結構的本機 Redis 列表:
用戶的主頁時間線將使用新推文進行更新,該新推文將存儲在內存緩存中。 我們將利用以下公共 REST API:
用戶時間線由用戶查看。
- Web 服務器接收來自客戶端的用戶時間線請求。
- 請求由 Web Server 發送到 Read API 服務器。
- 讀取 API 查詢 SQL 數據庫以獲取用戶時間範圍。
REST API 的工作方式與主頁時間線類似,但所有推文都來自用戶而不是他們關注的人。
用戶搜索關鍵字:
- Web 服務器接收來自客戶端的搜索請求。
- 請求由 Web 服務器發送到搜索 API 服務器。
第 4 步:Twitter 時間線
時間線創建是一項艱鉅的任務。 需要鏈接到 Web 或應用程序服務器的時間線生成服務器。
每次用戶登錄時,時間線服務都會跟踪關注者表中用戶的最新推文,並更新或刷新用戶的時間線。
我們在這裡不實施任何形式的排名系統; 相反,我們假設來自用戶關注者的前 5 條推文按創建時間順序顯示在時間線中。 我們可以維持 50 條推文刷新截止。 在達到該閾值後,我們仍然停止刷新或構建時間線,直到用戶刷新頁面。
高延遲和性能問題將來自實時用戶源創建。 相反,創建可以立即呈現的離線流是提高性能的最佳方法。 運行專用時間線服務器,定期對應用程序服務器執行 ping 操作,以根據創建時間刷新源。
排名算法應考慮關鍵信號並提供權重,以保證用戶的時間線不會受到來自他們所關注的一個或多個帳戶的材料的支配。
更準確地說,我們可以選擇與任何提要項的相關性相關的特徵,例如點贊數、評論數、分享數和更新時間。 這些標準中的每一個都應該用於對推文進行評級,然後該排名應該用於在時間軸上顯示推文。
當用戶的新聞源有新內容可用時,我們是否應該不斷提醒用戶? 用戶會發現,當有新數據可用時收到警報是有益的。 然而,在移動設備上,當數據使用成本相當昂貴時,可能會浪費帶寬。
因此,我們可以選擇不將數據推送到移動設備,而是允許用戶“拉動刷新”以獲取新帖子。
第五步:縮放設計
一個潛在的瓶頸是扇出服務。 擁有數百萬粉絲的 Twitter 用戶將不得不等待幾分鐘才能發布推文。 這可能會導致推文回复競爭,我們可以通過在服務時重新排序推文來避免這種情況。
我們還可以阻止擁有大量關注者的人傳播推文。 相反,我們可能會搜索來自高關注度個人的推文,將搜索結果與用戶的家庭時間線結果集成,然後在服務時對推文重新排序。
其他增強功能包括:
- 對於每個主頁時間線,內存緩存中僅保留幾百條推文。
- 在內存緩存中,僅保存活動用戶的主頁時間線信息。
- 如果用戶在過去 30 天內沒有活動,我們可以從 SQL 數據庫重建時間順序。
- 要找出用戶是誰,請利用用戶圖譜服務。
- 通過從 SQL 數據庫檢索推文將其添加到內存緩存。
- 推文信息服務只能保存一個月的推文。
- 在用戶信息服務中,僅保存活動用戶。
- 為了保持較低的延遲,搜索集群很可能需要在內存中維護推文。
結論
雖然Twitter是一個大組織,但它有更好的 對系統設計的理解。 我盡力為您提供 Twitter 時間軸的高級概述。
我希望您從中獲得有用的信息並能夠充分利用它。
發表評論