Twitter最新架構詳解,支撐5億使用者、1.5億活躍使用者

來源:互聯網
上載者:User
關鍵字 粉絲 所有 nbsp; 通過

Twitter如今在世界範圍內已擁有1.5億的活躍使用者,為了給使用者生成timeline(時間軸)需支撐30萬QPS,其firehose每秒同樣生成22MB資料。 整個系統每天傳輸tweet 4億條,並且只需要5分鐘就可以讓一條tweet從Lady Gaga手中呈現到她3100萬粉絲的螢幕上。 當下Twitter系統的規模及強大的輸送量確實惹人豔羨,然而在出道之初Twitter也只是個奮鬥在 RoR上的小網站而已,下面就一覽Twitter如何完成從RoR到以服務為核心的系統架構蛻變。

Twitter系統的一些特性:

1. 當下的Twitter已不滿足于Web Ap的現狀。 Twitter期望成為一組API,驅動世界範圍內的移動用戶端,成為世界級最大的即時事件鏈之一。

2. Twitter主導的是消費機制,而不是生產機制。 每秒讀取timeline的操作就會產生30萬次的查詢,而每秒的寫入請求只有6000左右。

3. 離群值,擁有巨量粉絲的個體開始變得普遍,大量粉絲擁有者發送tweet時會因為大量的擴散而變得緩慢。 Twitter試圖將這個延時控制在5秒內,但是也並非一直生效,特別是名人們發送tweet以及相互轉發變得越來越頻繁後。 這樣就導致轉發的內容可能比原始內容先一步到達共同粉絲的介面上,這樣一來,就高價值使用者來說,Twitter的主要精力必須從寫操作轉移到讀操作上。

4. 使用Redis集群處理Home Timeline(首頁時間軸,包含了眾多關注者的tweet),最大條數為800。

5. 從你關注的人和你點擊的連結,Twitter可以獲知一系列關於你的資訊。

6. 使用者最關心的是tweet內容,然而大部分的基礎設施卻和這些內容不相關。

7. 對如此複雜堆疊進行性能追蹤所需求的監視和調試系統往往非常複雜,同樣舊決策的影響會不時的出現。

Twitter面臨的挑戰

1. 1.5億的使用者以及支撐timeline(home及Search)的30萬QPS會讓最初的具體實現(Naive materialization)變得緩慢。

2. 最初的具體實現由大量選擇語句組成,遍及整個Twitter系統,曾今使用後被取締。

3. 使用一個基於寫的擴散方案。 在接收到tweet時,系統將做大量的計算以發現tweet需要呈現的使用者。 這將造就更快、方便的讀取,不要對讀做任何的計算。 由於所有的計算都被安排到寫去執行,每秒大約可處理4000個寫操作,比讀操作要慢一些。

Twitter的團隊合作

1. Platform Service團隊承擔起了Twitter核心基礎設施的一切事務:

他們負責Timeline Service、Tweet Service、User Service、Social Graph Service這些驅動Twitter平臺的所有元件。 內外用戶端使用了大致相同的API產品團隊不需要擔心任何規模相關針對協力廠商API的註冊應用過百萬做容量規劃,打造可擴展後端系統架構,在網站超出預期增長時要不斷的更換基礎設施。

2. Twitter還擁有一個架構團隊。 負責Twitter的整體架構,維護技術負債清單。

Pull和Push模式

1. 任何時刻都有使用者在Twitter上發佈內容,Twitter的任務就是考慮如何將消息同步發出並呈現到粉絲。

2. 真正的挑戰就是即時性約束,目標則是在5秒內將消息發送到粉絲:

交付意味著盡可能快的收集內容、投入互聯網,並且在盡可能短的時間內返回。 交付要做的是發佈到記憶體timeline集群、推送通知以及觸發電子郵件,其中包括所有的iOS、黑莓、安卓通知以及SMS。 Twitter是最大的SMS製造者Elections可以成為產生內容並且以最快速度擴散內容的最大動力

3. 兩種類型的timeline:user timeline(使用者時間軸,即指定使用者tweet頁)及home timeline

user timeline就是一個指定的使用者發佈的所有tweetHome timeline是你所有關注使用者user timeline的一個臨時合併商務規則。 非你關注人@你時,將會被自動過濾,轉發的tweet也可以被過濾。 在Twitter的規模做這些事情是非常有挑戰性的

Pull模式

1. 指向timeline,比如Twitter.com及hone_line API。 之所以將tweet發送給你,是因為你對其進行了請求。 基於Pull的交付:你通過REST API的調用向Twitter請求這些資料。

2. 查詢timeline,搜索API。 對資料庫進行查詢,盡可能快的返回所有匹配指定查詢的tweet。

Push模式

1. Twitter運行了一個巨型的即時事件系統,通過Firehose以每秒22M的速度推送tweet。

給Twitter打開一個socket,他們將會在150毫秒內完成所有公共tweet的推送。 任何時候給推送集群打開的socket都超過1百萬個使用類似搜尋引擎的firehose用戶端,所有公共的tweet都通過這些socket傳輸

2. 使用者流連接。 TweetDeck及Mac版的Twitter同樣通過這種方式驅動。 在登錄的時候,Twitter會查看你的社交圖,同樣也只會推送關注人的消息,重建home timeline,而不是在持久的連接過程中獲得同一個timeline。

3. 查詢API,發佈一個對tweet的持續查詢時,每當有新的tweet發佈,並且被認定匹配這個查詢,系統會將這條tweet發送給相應的socket。

高等級基於Pull的timeline

Tweet由一個寫入API生成,它將會通過負載等化器及TFE(Twitter Front End)這種做法很直接,所有的業務邏輯在tweet生成時就已經被執行。 隨著tweet的擴散過程開始,新生成的tweet會被投入一個大規模的Redis集群中。 每個tweet都會在3個不同的機器上做3個拷貝。 因為在Twitter的規模,每天會有大把的機器出故障。 粉絲的查詢基於Flock的社交圖服務,Flock會維護粉絲及粉絲清單:

Flock會返回一個接收者的社交圖,並且開始逐一查看所有存儲在Redis集群上的timelineRedis集群擁有TB級以上的記憶體每次投遞4K左右的tweetRedis使用原生的表結構如果你有2萬個粉絲, 負責粉絲查詢的守護進程將會確認2萬個使用者在Redis集群中的具體位置,然後它會橫跨整個Redis集群將Tweet ID插入相應的清單中。 所以當你有2萬個粉絲時,每條tweet的寫入都會造成2萬個插入操作。 儲存的資訊包括新生成tweet的ID、tweet編寫者ID以及一個4位元組大小的狀態資訊(轉發、評論或者是其它相關)。 Home timeline位於Redis集群中,每個有800條tweet。 如果你向後翻太多頁就沒了,RAM是限制清單tweet數量的最大瓶頸。 為了控制延時,所有活躍使用者都存儲在記憶體中。 活躍使用者的定義是在30天內有登陸過Twitter,當然這個規則可以根據緩存容量、實際使用等進行修改。 如果你不是活躍使用者,tweet就不會被放入緩存。 只對home timeline進行存檔(持久化。 PS:個人覺得這裡應該是user timeline,如果是home timeline下文的重建方法顯然不科學,歡迎大家討論)如果home timeline不在Redis集群中,則需要經歷一個重建的過程:

對社交圖服務進行查詢,找出你關注的人。 分別的訪問磁片獲取每個人的資料,然後將他們送回Redis。 通過Gizzard使用MySQL處理磁片存儲,這將抽象出所有SQL事務並且提供了全域備份。

鑒於每條tweet都會做3個備份,如果其中某台機器發生故障,他們無需對這台機器上的所有timeline進行重建。 當tweet被轉發時,將會存儲一個指向原tweet的指標。

當做home timeline查詢時,Timeline Service將被調用。 Timeline Service確認home timeline究竟存在哪台機器上:

鑒於timeline備份在3個不同的機器上,所以需要運行3個不同的雜湊環。 一旦找著其中一個,就會盡可能快的返回結果。 雖然這個過程會花費稍長的一點時間,但是讀的處理仍然很快。 從冷緩存到瀏覽器上呈現大約需要2秒,其中一個API的調用時間大約400毫秒。

鑒於timeline只包含了tweet的ID,所以還必須要做tweet內容的查詢。 確定了ID以後,Twitter將通過T-bird並行獲取tweet的內容。 Gizmoduck是個使用者服務,而Tweetypie則是個tweet物件服務,每個服務都擁有自己的獨立緩存。 使用者緩存使用的是memcache集群,緩存了所有使用者。 Tweetypie處理的是上個月的內容,它將一半的tweet儲存在它獨立的memcache集群中,當然這個部分服務的是內部使用者。 內容的過濾同樣會省卻一些讀取時間,比如過濾掉法國的納粹相關,這些內容的讀取時間在呈現之前就被過濾了。

高等級的搜索

1. 所有的計算都通過讀來解決,這讓寫更加簡潔

2. 當有tweet生成時,Ingester會做相應的語法分析和索引,隨後會將其傳入Early Bird機器中。 Early Bird屬於Lucene的修改版本,同時索引都儲存在記憶體中。

3. 在tweet擴散過程中,它可能會被儲存在多個home timeline中,其個數由粉絲的數量決定。 然而在Early Bird中,一個tweet只會被存入一個Early Bird機器中(不包括備份)。

4. Blender負責timeline的查詢,橫跨整個資料中心做集散操作。 它對每個Early Bird做查詢,以發現與查詢準則匹配的內容。 如果你搜索「New York Times」,Blender會查詢資料中心的所有分片並返回結果,同時還會做分類、合併及重新排序等。 排序的規則基於互動的資料,也就是轉發、收藏及評論的數量等。

5. 互動的資訊使用寫的模式完成,這裡會建立一個互動timeline。 如果你收藏或者回復一個tweet,將會觸發對互動timeline的修改;類似于home timeline,它同樣由一系列的互動ID組成,比如收藏ID、評論ID等等。

6. 所有這些資訊都被送到Blender。 以讀的方式進行重算、合併以及分類,返回的結果就是search timeline為你呈現的介面。

7. Discovery是個基於你相關資訊的定制搜索,這些資訊主要來自你關注的人、打開的連結,而重新排序的規則同樣基於這些資訊。

Search和Pull是相反的

1. 搜索和pull看起來非常相似,其實他們有著本質上的區別。

2. 在home timeline情況下:

寫。 一個寫tweet的動作會觸發一個O(n)規模的Redis集群寫入操作,n的值取決於粉絲的數量,由此可見處理Lady Gaga及Barack Obama這樣擁有數千萬粉絲的名人將會很麻煩。 Redis集群上的資訊都會寫入磁片,Flock集群會將user timeline儲存到磁片上,但是通常情況下timeline在Redis集群的記憶體中都可以發現。 讀。 通過API或網路查找Redis是一個常數規模的操作。 Twitter對home tiimeline的讀操作做了高可用性優化,讀操作只花費數十毫秒。 這裡也可以看出Twitter主導的是一個消費機制,而不是生產機制。 每秒可處理30萬個讀操作,而寫操作每秒處理6000個。

3. 搜索timeline情況:

寫。 Tweet生成,並且傳輸到Ingester,只會寫入一個Early Bird機器。 一個tweet處理的時間大約為5秒,其中包括了排隊及尋找待寫入的Early Bird 機器。 讀。 每個讀請求都會觸發一個O(n)規模的集群讀操作。 讀大約需要100毫秒,搜索不涉及到存檔。 所有的Lucene索引都保存在RAM中,所以聚散是非常有效率的,因為不涉及到磁片。

4. Tweet的內容基本上與大多數的基礎設施都是無關的。 T-bird存儲了所有tweet內容,大部分的tweet內容都是在記憶體中。 如果沒有的話,可以通過select查詢將其拉回記憶體。 與tweet內容相關的功能非常少,搜索就是其中一個,而Home timeline則完全不關心。

未來的工作

1. 如何將這條資料的管道打造的更快更有效

2. 在5秒內做到tweet的擴散,但是並不是時刻的奏效,特別是越來越多的高粉單位。

3. Twitter是非對稱的關注,只有你關注人的tweet才會呈現給你。 Twitter可以從這些單向關注中獲取你更多的資訊,有些單向關注同樣還影射出一些社會契約。

4. 問題一般發生在大基數的圖上:@ladygaga擁有3100萬粉絲,@katyperry擁有2800萬粉絲,@justinbieber擁有2800萬粉絲,@barackobama擁有2300萬粉絲。

5. 大批量粉絲的擁有者每發送一條tweet將造成資料中心大量的寫入操作,而隨著越來越多名人之間的交互,挑戰變得更加的艱巨。

6. 這些需要擴散給大批量使用者的tweet是Twitter最大的挑戰,在關注這些名人的共同粉絲中,經常會出現回復tweet比原文更早一步送達的情況。 他們在網站中引入競態條件,比如最近關注Lady Gaga的粉絲可能會比老早之前關注的粉絲早5分鐘看到tweet內容。 比如說一個使用者先收到了tweet,並進行回復,然而這時候Lady Gaga的原微博並沒有擴散完畢,這樣就會存在有些使用者先看到回復的情況,為使用者造成很大的困擾。 Tweet通過ID進行排序,因為他們大多數是單調遞增的,然而在如此粉絲規模下,這種做法並不奏效。

7. 尋找讀和寫途徑的合併,不再做如此大規模的擴散;比如傳播Taylor Swift新生成的tweet,取代在生成時進行擴散tweet ID,而是在讀取時候就進行合併。 通過平衡讀寫途徑,節省百分之幾十的資源。

解耦相關

1. 基於Twitter通過各種途徑傳播tweet,解耦可以讓不同技術團隊獨立完成自己的工作。

2. 基於性能問題,系統也需要解耦。 Twitter過去使用的一直是完全同步模式,而在兩年前因為性能問題他們停用了這個模式。 設備接收一個tweet需要145毫秒,接收完畢後就斷開所有用戶端連接,這麼做同樣也因為技術負債。 寫的路徑由Ruby驅動,通過MRI實現,一個單線程伺服器,每次Unicorn worker分配都會耗盡所有處理性能。 每當有tweet流入,Ruby就會接收它,將它放到一個佇列中然後斷開連結。 他們在每台伺服器上只運行45-48個進程,這樣的話每個主機殼能同時處理的tweet數量也是這麼多,所以他們必須盡可能快的斷開連接。

3. 當下的tweet已經通過非同步模式來處理,而這些討論也都是建立在非同步之上。

監視相關

1. 系統性能即時儀錶盤

2. 使用VIZ系統監視每個集群,請求Timeline Service並從Scala集群獲取資料的平均時間為5毫秒。

3. 基於Google Dapper系統的Zipkin,工程師可以通過Zipkin對請求的細節進行監視,比如獲取請求所訪問的服務及請求時間,這樣就可以獲知每個請求的性能細節。 這樣就可以通過每個階段耗費的時間對系統進行調試,同樣也可以從總體上看從請求到交付耗費的時間。 花費了兩年的時間,Twitter將活躍使用者的timeline降到2毫秒。

部分統計資料:

如果你有100萬個粉絲,每個tweet將耗費數秒的時間來傳播Tweet輸入統計:每天4億條;日平均統計5000每秒;日統計峰值7000每秒;大事件期間高於1.2萬每秒。 Timeline交付統計:每天300億次(更多資料見原文)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.