Twitter系統架構參考Push、Pull模式每時每刻都有用戶在Twitter上發表內容,Twitter工作是規劃如何組織內容並把它發送用戶的粉絲。 實時是真正的挑戰,5秒內將消息呈現給粉絲是現階段的目標。 投遞意味著內容、投入互聯網,然後儘可能快的發送接收。 投遞將歷時數據放入存儲棧,推送通知, ...
Twitter系統架構參考
Push、Pull模式
- 每時每刻都有用戶在Twitter上發表內容,Twitter工作是規劃如何組織內容並把它發送用戶的粉絲。
- 實時是真正的挑戰,5秒內將消息呈現給粉絲是現階段的目標。
- 投遞意味著內容、投入互聯網,然後儘可能快的發送接收。
- 投遞將歷時數據放入存儲棧,推送通知,觸發電子郵件,iOS、黑莓及Android手機都能被通知到,還有簡訊。
- Twitter是世界上活躍中最大的信息發送機。
- 推薦是內容產生並快速傳播的巨大動力。
- 兩種主要的時間軸:用戶的及主頁的。
- 用戶的時間軸特定用戶發送的內容。
- 主頁時間表是一段時間內所有你關註用戶發佈的內容。
- 線上規則是這樣的:@別人是若被@的人你未關註的話將被隔離出來,回覆一個轉發可以被過濾掉。
- 這樣在Twitter對系統是個挑戰。
- Pull模式
- 有針對性的時間軸。像http://twitter.com主頁和home_timeline的API。你請求它才會得到數據。拉請求的不少:通過REST API請求從Twitter獲取數據。
- 查詢時間軸,搜索的API。查詢並儘可能快的返回所有匹配的推特。
- Push模式
- Twitter運行著一個最大的實時事件系統,出口帶寬22MB/秒。
- 和Twitter建立一個連接,它將把150毫秒內的所有消息推送給你。
- 幾乎任何時候,Push服務簇上大約有一百萬個連接。
- 像搜索一樣往出口發送,所有公共消息都通過這種方式發送。
- 不,你搞不定。(實際上處理不了那麼多)
- 用戶流連接。 TweetDeck 和Twitter的Mac版都經過這裡。登錄的時,Twitter會查看你的社交圖,只會推送那些你關註的人的消息,重建主頁時間軸,而不是在持久的連接過程中使用同一個時間軸 。
- 查詢API,Twitter收到持續查詢時,如果有新的推特發佈並且符合查詢條件,系統才會將這條推特發給相應的連接。
- Twitter運行著一個最大的實時事件系統,出口帶寬22MB/秒。
Twitter架構
時間軸
- 短消息(Tweet)通過一個寫API傳遞進來。通過負載平衡以及一個TFE(短消息前段),以及一些其它的沒有被提到的設施。
- 這是一條非常直接的路徑。完全預先計算主頁的時間軸。所有的業務邏輯在短消息進入的時候就已經被執行了。
- 緊接著扇出(向外發送短消息)過程開始處理。進來的短消息被放置到大量的Redis集群上面。每個短息下在三個不同的機器上被覆制3份。在Twitter 每天有大量的機器故障發生。
- 扇出查詢基於Flock的社交圖服務。Flock 維護著關註和被關註列表。
- Flock 返回一個社交圖給接受者,接著開始遍歷所有存儲在Redis 集群中的時間軸。
- Redis 集群擁有若幹T的記憶體。
- 同時連接4K的目的地。
- 在Redis 中使用原生的鏈表結構。
- 假設你發出一條短消息,並且你有20K個粉絲。扇出後臺進程要做的就是在Redis 集群中找出這20K用戶的位置。接著它開始將短消息的ID 註入到所有這些列表中。因此對於每次寫一個短消息,都有跨整個Redis集群的20K次的寫入操作。
- 存儲的是短消息的ID, 最初短消息的用戶ID, 以及4個位元組,標識這條短消息是重發還是回覆還是其它什麼東東。
- 你的主頁的時間軸駐扎在Redis集群中,有800條記錄長。如果你向後翻很多頁,你將會達到上限。記憶體是限制資源決定你當前的短消息集合可以多長。
- 每個活躍用戶都存儲在記憶體中,用於降低延遲。
- 活躍用戶是在最近30天內登陸的twitter用戶,這個標準會根據twitter的緩存的使用情況而改變。
- 只有你主頁的時間軸會存儲到磁碟上。
- 如果你在Redis 集群上失敗了,你將會進入一個叫做重新構建的流程。
- 查新社交圖服務。找出你關註的人。對每一個人查詢磁碟,將它們放入Redis中。
- MySQL通過Gizzard 處理磁碟存儲,Gizzard 將SQL事務抽象出來,提供了全局複製。
- 通過複製3次,當一臺機器遇到問題,不需要在每個數據中心重新構建那台機器上的時間軸。
- 如果一條短消息是另外一條的轉發,那麼一個指向原始短消息的指針將會存儲下來。
- 當你查詢你主頁的時間軸時候,時間軸服務將會被查詢。時間軸服務只會找到一臺你的時間軸所在的機器。
- 高效的運行3個不同的哈希環,因為你的時間軸存儲在3個地方。
- 它們找到最快的第一個,並且以最快速度返回。
- 需要做的妥協就是,扇出將會花費更多的時間,但是讀取流程很快。大概從冷緩存到瀏覽器有2秒種時間。對於一個API調用,大概400ms。
- 因為時間軸只包含短消息ID, 它們必須”合成”這些短消息,找到這些短消息的文本。因為一組ID可以做一個多重獲取,可以並行地從T-bird 中獲取短消息。
- Gizmoduck 是用戶服務,Tweetypie 是短消息對象服務。每個服務都有自己的緩存。用戶緩存是一個memcache集群 擁有所有用戶的基礎信息。Tweetypie將大概最近一個半月的短消息存儲在memcache集群中。這些暴露給內部的用戶。
- 在邊界將會有一些讀時過濾。例如,在法國過濾掉納粹內容,因此在發送之前,有讀時內容剝離工作。
搜索
- 與Pull相反,所有計算都在讀時執行,這樣可以使寫更簡單。
- 產生一條推特時,Ingester會對其做語法分析找出新建索引的一切東西,然後將其傳入一臺Early Bird機器。Early Bird是Lucene的修改版本,索引儲存在記憶體中。
- 在推特的分發過程中可能被儲存在多個由粉絲數量決定的主頁時間軸中,一條推特只會存入一個Early Bird機器中(不包括備份)。
- Blender進行時間軸的跨數據中心集散查詢。為發現與查詢條件匹配的內容它查詢每個Early Bird。如果你搜索“紐約時報”,所有分片將被查詢,結果返回後還會做分類、合併及重排序等。排序是基於社會化度量的,這些度量基於轉發、收藏及評論的數量等。
- 互動信息是在寫上完成的,這裡會建立一個互動時間軸。當收藏或回覆一條推特時會觸發對互動時間軸的修改,類似於主頁時間軸,它是一系列的活躍的ID,有最受喜歡的ID,新回覆ID等。
- 所有這些都被送到Blender,在讀路徑上進行重計算、合併及分類,返回的結果就是搜索時間軸上看到的東西。
- Discovery是基於你相關信息的定製搜索,Twitter通過你關註的人、打開的鏈接瞭解你的信息,這些信息被應用在Discovery搜索上,重新排序也基於這些信息。
Search和Pull是相反的
- Search和Pull明顯的看起來很相似,但是他們在某些屬性上卻是相反的。
- 在home timeline時:
- 寫操作。tweet寫操作引發O(n)個進程寫入Redis集群,n代表你的粉絲,如果是這樣,處理Lady Gaga或是Obama百萬粉絲的數據就得用10s的時間,那是很難接受的。所有的Redis集群都支持硬碟處理數據,但是一般都是在RAM里操作的。
- 讀操作。通過API或是網路可用O(1)的時間來找到Redis機器。Twitter在尋找主頁路徑方面做了大量的優化。讀操作可在10毫秒完成。所有說Twitter主導消費機制而不是生產機制。每秒可處理30萬個請求和6000 RPS寫操作。
- 在搜索timeline時:
- 寫操作。一個tweet請求由Ingester收到並有一個Early Bird機器來處理。寫操作時O(1).一個tweet需要5秒的處理時間,其包括排隊等待和尋找路徑。
- 讀操作。讀操作引發O(n)個集群讀操作。大多數人不用search,這樣他們可以在存儲tweets上面更加有效,但是他們得花時間。讀需要100毫秒,search不涉及硬碟操作。全部Lucene 索引表都放入RAM,這樣比放在硬碟更加有效。
- tweet的內容和基礎設施幾乎沒什麼關係。T-bird stores負責tweet所有的東西。大多數tweet內容是放在RAM處理的。如有沒再記憶體中,就用select query將內容抓到記憶體中。只有在search,Trends,或是What’s Happening pipelines中涉及到內容,hone timeline對此毫不關心。
展望:
當這些人中有人發微博的時候,數據中心需要寫大量微薄到各個關註者。當他們開始聊天時候,這是非常大的挑戰,而這時刻都在發生著。
- 這些高關註度的Fanout用戶是Twitter最大的挑戰。在名人原始微薄發出到關註用戶之前,回覆一直可以看到。這導致整個網站紊亂。Lady Gaga的一條微薄到關註用戶需要幾分鐘的時間,所以關註者看到這條微薄時間是在不同時間點上。有些人可能需要大概5分鐘的時間才能看到這條微薄,這遠遠落後於其他人。可能早期收到微薄的用戶已經收到了回覆的列表,而這時候回覆還正在處理之中,而fanout還一直進行著所以回覆被加了進來。這都發生在延遲關註者收到原始微薄之前。這會導致大量用戶混亂。微薄發出之前是通過ID排序的,這導致它們主要是單調增長地,但是那種規模下這不能解決問題。對高值的fanouts隊列一直在備份。
- 試圖找到解決合併讀和寫路徑的方法。不在分發高關註度用戶微薄。對諸如Taylor Swift的人不會在額外的處理,只需要在讀時候,他的時間點併入即可。平衡讀和寫的路徑。可以節約百分之10s的計算資源。
解耦
- Tweet通過很多的方式解除關聯,主要地通過彼此解耦的方式。搜索、推送、郵件興趣組以及主頁時間軸可以彼此獨立的工作。
- F由於性能的原因,系統曾經被解耦過。Twitter曾經是完全同步地方式的,由於性能的原因2年前停止了。提取一個tweet到tweet介面需要花費145微秒,接著所有客戶端被斷開連接。這是歷史遺留的問題。寫路徑是通過MRI用一個Ruby驅動的程式,一個單線程的服務。每次一個獨立的woker被分配的時候,處理器都會被耗盡。他們希望有能力儘可能快的去釋放客戶端連接。一個tweet進來了。Ruby處理了它。把它插入隊列,並且斷開連接。他們僅僅運行大概45-48進程/盒。所以他們只能並行處理同樣多tweets/盒,所以他們希望儘可能快的斷開連接。
- Tweets 被切換到非同步路徑方式,我們討論所有東西都被剔除了。
監控
- 辦公室四處的儀錶盤顯示了系統在任何給定時間系統的運行狀態。
- 如果你有100萬的關註者,將會要花費好幾分鐘到分發到所有tweets。
- Tweets 入口統計:每天400兆的tweets。日平均每秒種5000;日高峰時每秒7000;有事件時候是每秒超過12000。
- 時間軸分發統計:30b分發/日(約21M/分鐘);3.5秒@p50(50%分發率)分發到1M;300k 分發/秒;@p99 大概需要5分鐘。
- 一個名為VIZ的監控系統監控各個集群。時間軸服務檢索數據集群數據的平均請求時間是5毫秒。@p99需要100毫秒。@p99.9需要請求磁碟,所以需要大概好幾百毫秒。
- Zipkin 是基於谷歌Dapper的系統。利用它可以探測一個請求,查看他點擊的每一個服務,以及請求時間,所以可以獲得每個請求的每一部分性能細節信息。你還還可以向下鑽取,得到不同時間周期下的每單個的請求的詳細信息。大部分的時間是在調試系統,查看請求時間都消耗的什麼地方。它也可以展示不同緯度的聚合統計,例如,用來查看fanout和分發了多久。大概用了2年長的一個工程,來把活躍用戶時間線降到2毫秒。大部分時間用來剋服GC停頓,memchache查詢,理解數據中心的拓撲應該是怎麼樣結構,最後建立這種類型集群。
今天先到這兒,希望對雲原生,技術領導力, 企業管理,系統架構設計與評估,團隊管理, 項目管理, 產品管管,團隊建設 有參考作用 , 您可能感興趣的文章:
領導人怎樣帶領好團隊
構建創業公司突擊小團隊
國際化環境下系統架構演化
微服務架構設計
視頻直播平臺的系統架構演化
微服務與Docker介紹
Docker與CI持續集成/CD
互聯網電商購物車架構演變案例
互聯網業務場景下消息隊列架構
互聯網高效研發團隊管理演進之一
消息系統架構設計演進
互聯網電商搜索架構演化之一
企業信息化與軟體工程的迷思
企業項目化管理介紹
軟體項目成功之要素
人際溝通風格介紹一
精益IT組織與分享式領導
學習型組織與企業
企業創新文化與等級觀念
組織目標與個人目標
初創公司人才招聘與管理
人才公司環境與企業文化
企業文化、團隊文化與知識共用
高效能的團隊建設
項目管理溝通計劃
構建高效的研發與自動化運維
某大型電商雲平臺實踐
互聯網資料庫架構設計思路
IT基礎架構規劃方案一(網路系統規劃)
餐飲行業解決方案之客戶分析流程
餐飲行業解決方案之採購戰略制定與實施流程
餐飲行業解決方案之業務設計流程
供應鏈需求調研CheckList
企業應用之性能實時度量系統演變
如有想瞭解更多軟體設計與架構, 系統IT,企業信息化, 團隊管理 資訊,請關註我的微信訂閱號:
作者:Petter Liu
出處:http://www.cnblogs.com/wintersun/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
該文章也同時發佈在我的獨立博客中-Petter Liu Blog。