Badoo 中儲存與分享照片的架構

Badoo 中儲存與分享照片的架構

阿爾喬姆·傑尼索夫( 博0rsh201, Badoo上)

Badoo 是世界上最大的交友網站。 目前我們在全球擁有約 330 億註冊用戶。 但就我們今天的對話而言,更重要的是我們儲存了大約 3 PB 的使用者照片。 我們的用戶每天上傳約 3,5 萬張新照片,閱讀量約為 每秒 80 萬個請求。 這對我們的後端來說是相當多的,有時會遇到困難。

Badoo 中儲存與分享照片的架構

我將討論這個系統的設計,它一般儲存和發送照片,我將從開發人員的角度來看它。 我們將簡要回顧它的發展過程,其中我將概述主要里程碑,但我只會更詳細地討論我們目前正在使用的解決方案。

現在讓我們開始吧。


正如我所說,這將是一次回顧展,為了從某個地方開始,讓我們舉一個最常見的例子。

Badoo 中儲存與分享照片的架構

我們有一個共同的任務,我們需要接受、儲存和發送用戶照片。 在這種形式中,任務是通用的,我們可以使用任何東西:

  • 現代雲端存儲,
  • 盒裝解決方案,現在也有很多;
  • 我們可以在我們的資料中心設置幾台機器,並在它們上面放置大硬碟並在那裡儲存照片。

從歷史上看,無論現在還是過去(當時它還處於起步階段),Badoo 都運行在我們自己的 DC 內的自己的伺服器上。 因此,這個選擇對我們來說是最佳選擇。

Badoo 中儲存與分享照片的架構

我們只是拿了幾台機器,稱之為“照片”,然後我們就得到了一個儲存照片的叢集。 但似乎缺少了一些東西。 為了讓這一切發揮作用,我們需要以某種方式確定我們將在哪台機器上儲存哪些照片。 在這裡,也沒有必要開放美國。

Badoo 中儲存與分享照片的架構

我們在儲存中添加一些包含用戶資訊的欄位。 這將是分片鍵。 在我們的例子中,我們稱之為 place_id,這個地點 id 指向儲存使用者照片的位置。 我們製作地圖。

在第一階段,這甚至可以手動完成 - 我們說該用戶在這樣的地方的照片將登陸這樣的伺服器。 借助這張地圖,我們始終知道用戶何時上傳照片、將其保存在哪裡以及從哪裡提供照片。

這是一個絕對微不足道的方案,但它具有相當顯著的優點。 首先,正如我所說,它很簡單;第二,透過這種方法,我們可以透過簡單地交付新車並將其添加到地圖中來輕鬆水平擴展。 您不需要做任何其他事情。

我們有一段時間就是這樣。

Badoo 中儲存與分享照片的架構

這是2009年左右的事。 他們交付汽車,交付...

在某些時候我們開始注意到這個方案有一定的缺點。 有什麼缺點?

首先,能力有限。 我們無法將盡可能多的硬碟塞到一台實體伺服器上。 隨著時間的推移和數據集的增長,這已經成為一個確定的問題。

第二。 這是一種非典型的機器配置,因為此類機器很難在其他叢集中重複使用;它們非常具體,即它們的性能應該較弱,但同時具有大硬碟。

這都是 2009 年的情況,但原則上這些要求仍然適用。 我們有一個回顧,所以 2009 年一切都非常糟糕。

最後一點是價格。

Badoo 中儲存與分享照片的架構

當時價格非常昂貴,我們需要尋找一些替代方案。 那些。 我們需要以某種方式更好地利用資料中心的空間和所有這些所在的實體伺服器。 我們的系統工程師開始了一項大型研究,他們審查了許多不同的選項。 他們也研究了 PolyCeph 和 Lustre 等叢集檔案系統。 有效能問題且操作相當困難。 他們拒絕了。 我們嘗試透過 NFS 將整個資料集安裝在每輛車上,以便以某種方式對其進行擴展。 閱讀也很糟糕,我們嘗試了不同供應商的不同解決方案。

最後,我們決定使用所謂的儲存區域網路。

Badoo 中儲存與分享照片的架構

這些是專門為儲存大量資料而設計的大型 SHD。 它們是帶有磁碟的架子,安裝在最終的光學輸出機器上。 那。 我們有某種類型的機器池,非常小,這些 SHD 對我們的發送邏輯來說是透明的,即讓我們的 nginx 或任何其他人能夠處理這些照片的請求。

這個決定有明顯的優勢。 這是SHD。 它的目的是存儲照片。 這比簡單地為機器配備硬碟更便宜。

第二加。

Badoo 中儲存與分享照片的架構

這是容量變大了很多,即我們可以在更小的體積中容納更多的儲存空間。

但也有很快就會出現的缺點。 隨著系統上的使用者數量和負載的成長,效能問題開始出現。 這裡的問題非常明顯 - 任何設計用於在小容量中存儲大量照片的 SHD 通常都會受到密集讀取的影響。 對於任何雲端儲存或其他任何東西來說實際上都是如此。 現在我們還沒有一個可以無限擴展的理想存儲,你可以往裡面塞任何東西,而且它能很好地容忍讀取。 尤其是休閒讀物。

Badoo 中儲存與分享照片的架構

就像我們的照片一樣,因為照片的請求不一致,這會極大地影響它們的效能。

即使根據今天的數據,如果我們在連接儲存的電腦上獲得超過 500 RPS 的照片速度,問題就已經開始了。 這對我們來說已經夠糟糕了,因為用戶數量不斷增長,事情只會變得更糟。 這需要以某種方式進行優化。

為了優化,我們當時決定,顯然,要查看負載曲線 - 一般來說,正在發生什麼,需要優化什麼。

Badoo 中儲存與分享照片的架構

在這裡,一切都掌握在我們手中。

我已經在第一張投影片中說過:我們每秒鐘有 80 萬個閱讀請求,而每天只有 3,5 萬次上傳。 也就是說,這是三個數量級的差異。 顯然,閱讀需要優化,而且具體如何優化也很清楚。

還有一個小點。 服務的具體細節是,一個人註冊、上傳照片,然後開始主動查看其他人,喜歡他們,並主動向其他人展示。 然後他找到伴侶或找不到伴侶,這取決於結果如何,並停止使用該服務一段時間。 此時此刻,當他使用它時,他的照片非常熱門——它們很受歡迎,很多人都在觀看它們。 一旦他停止這樣做,他很快就會像以前一樣不再與其他人接觸,幾乎從來沒有人要求他拍照。

Badoo 中儲存與分享照片的架構

那些。 我們有一個非常小的熱數據集。 但同時也有很多人對他提出要求。 這裡一個完全顯而易見的解決方案是添加快取。

具有 LRU 的快取將解決我們所有的問題。 我們在做什麼?

Badoo 中儲存與分享照片的架構

我們在具有存儲的大型集群前面添加了另一個相對較小的集群,稱為照片緩存。 這本質上只是一個快取代理。

它是如何從內部運作的? 這是我們的用戶,這是儲存。 一切都和以前一樣。 我們在中間加入什麼?

Badoo 中儲存與分享照片的架構

只是一台有實體本機磁碟的機器,速度很快。 例如,這是 SSD 的情況。 並且某種本機快取儲存在該磁碟上。

它是什麼樣子的? 用戶發送照片請求。 NGINX 首先在本機快取中查找它。 如果沒有,則只需 proxy_pass 到我們的存儲,從那裡下載照片並將其提供給用戶。

但這非常平庸,不清楚裡面發生了什麼事。 它的工作原理是這樣的。

Badoo 中儲存與分享照片的架構

緩存在邏輯上分為三層。 當我說「三層」時,這並不意味著存在某種複雜的系統。 不,這些只是檔案系統中的三個目錄:

  1. 這是剛從代理下載的照片所在的緩衝區。
  2. 這是一個熱緩存,用於儲存當前主動請求的照片。
  3. 還有一個冷緩存,當收到的請求較少時,照片會逐漸從熱緩存中推出。

為此,我們需要以某種方式管理該緩存,需要重新排列其中的照片等。 這也是一個非常原始的過程。

Badoo 中儲存與分享照片的架構

Nginx 只是將每個請求寫入 RAMDisk access.log,其中指示當前所服務的照片的路徑(當然是相對路徑)以及所服務的分區。 那些。 它可能會說“照片 1”,然後是緩衝區、熱快取、冷快取或代理。

根據這一點,我們需要以某種方式決定如何處理照片。

我們在每台機器上運行一個小守護程序,它不斷讀取此日誌並將有關某些照片的使用情況的統計資料儲存在記憶體中。

Badoo 中儲存與分享照片的架構

他只是在那裡收集、保留計數器並定期執行以下操作。 他將主動請求的照片(有很多請求)移動到熱緩存,無論它們在哪裡。

Badoo 中儲存與分享照片的架構

很少被要求且請求頻率較低的照片會逐漸從熱緩存推出到冷緩存。

Badoo 中儲存與分享照片的架構

當我們用完快取空間時,我們只是開始不加區別地從冷緩存中刪除所有內容。 順便說一句,這很有效。

為了在將照片代理到緩衝區時立即保存照片,我們使用 proxy_store 指令,緩衝區也是 RAMDisk,即對於用戶來說,它的工作速度非常快。 這涉及緩存伺服器本身的內部結構。

剩下的問題是如何在這些伺服器之間分發請求。

假設有一個由二十台儲存機器和三台快取伺服器組成的叢集(事情就是這樣發生的)。

Badoo 中儲存與分享照片的架構

我們需要以某種方式確定哪些請求針對哪些照片以及將它們放在哪裡。

最常見的選項是循環法。 還是偶然做的?

這顯然有很多缺點,因為在這種情況下我們使用快取的效率會非常低。 請求將落在一些隨機機器上:在這裡它被緩存,但在下一台機器上它不再存在。 如果這一切都奏效,那將是非常糟糕的。 即使集群中的機器數量很少。

我們需要以某種方式明確地確定哪個伺服器來處理哪個請求。

有一種平庸的方式。 我們從 URL 中取得雜湊值,或從 URL 中的分片鍵中取得雜湊值,然後將其除以伺服器數量。 將工作? 將要。

Badoo 中儲存與分享照片的架構

那些。 我們有一個2%的請求,例如,對於某些“example_url”,它總是會落在索引為“XNUMX”的伺服器上,並且快取將不斷被盡可能最好地處理。

但這種方案中存在重新分片的問題。 重新分片——我的意思是改變伺服器的數量。

假設我們的快取叢集無法再應對,我們決定再增加一台機器。

我們來補充一下。

Badoo 中儲存與分享照片的架構

現在一切都不能被三整除,而是可以被四整除。 因此,我們以前擁有的幾乎所有金鑰、幾乎所有 URL 現在都位於其他伺服器上。 整個緩存只是短暫地失效了。 所有請求都落在我們的儲存叢集上,它變得不舒服、服務失敗和用戶不滿意。 我不想那樣做。

這個選項也不適合我們。

那。 我們該做什麼? 我們必須以某種方式有效地利用緩存,一遍又一遍地將相同的請求發送到同一台伺服器上,但要抵制重新分片。 而且有這樣的解決方案,並沒有那麼複雜。 這稱為一致性哈希。

Badoo 中儲存與分享照片的架構

這看起來像什麼?

Badoo 中儲存與分享照片的架構

我們從分片鍵中獲取一些函數並將其所有值傳播到圓上。 那些。 在點0處,它的最小值和最大值收斂。 接下來,我們將所有伺服器放置在同一個圓上,大致如下:

Badoo 中儲存與分享照片的架構

每個伺服器由一個點定義,順時針方向到達該點的扇區相應地由該主機提供服務。 當請求發送給我們時,我們立即看到,例如,請求 A - 它有一個哈希 - 並且由伺服器 2 提供服務。請求 B - 由伺服器 3 提供服務。等等。

Badoo 中儲存與分享照片的架構

在這種情況下重新分片時會發生什麼?

Badoo 中儲存與分享照片的架構

我們不會像以前那樣使整個快取無效,也不會移動所有密鑰,而是將每個扇區移動一小段距離,以便相對而言,我們要添加的第六個伺服器適合可用空間,並且我們將其添加到那裡。

Badoo 中儲存與分享照片的架構

當然,在這種情況下,鑰匙也會移出。 但他們的離開比以前弱得多。 我們看到前兩個金鑰保留在他們的伺服器上,而快取伺服器僅針對最後一個金鑰進行了更改。 這工作起來非常有效,如果您增量新增主機,那麼這裡就不會有大問題。 你一次添加一點,等到快取再次滿了,一切就正常了。

唯一的問題仍然是拒絕。 讓我們假設某種汽車出了故障。

Badoo 中儲存與分享照片的架構

我們此時並不真的想重新產生此映射,使部分快取無效,等等,例如,如果機器重新啟動,並且我們需要以某種方式服務請求。 我們只需在每個站點保留一個備份照片緩存,作為當前關閉的任何電腦的替代品。 如果我們的一台伺服器突然無法使用,流量就會流向那裡。 當然,我們那裡沒有任何緩存,即雖然很冷,但至少用戶的請求得到了處理。 如果這是一個很短的間隔,那麼我們就會完全平靜地體驗它。 只是存儲負載增加了。 如果這個間隔很長,那麼我們已經可以做出決定 - 是否從地圖上刪除該伺服器,或者可能用另一個伺服器取代它。

這是關於快取系統的。 讓我們看看結果。

看起來這裡並沒有什麼複雜的事。 但這種管理快取的方法給了我們大約 98% 的欺騙率。 那些。 每秒這80萬個請求中,只有1600個到達存儲,這是完全正常的負載,他們平靜地忍受它,我們總是有儲備。

我們將這些伺服器放置在三個 DC 中,並獲得了三個存在點 - 布拉格、邁阿密和香港。

Badoo 中儲存與分享照片的架構

那。 他們或多或少位於我們每個目標市場的本地。

作為一個不錯的獎勵,我們得到了這個快取代理,CPU 實際上是空閒的,因為它並不需要提供內容。 在那裡,我們使用 NGINX+ Lua 實作了很多功利邏輯。

Badoo 中儲存與分享照片的架構

例如,我們可以嘗試使用 webp 或漸進式 jpeg(這些是有效的現代格式),看看它如何影響流量,做出一些決定,在某些國家/地區啟用它等; 即時動態調整大小或裁剪照片。

這是一個很好的用例,例如,您有一個顯示照片的行動應用程序,並且該行動應用程式不希望浪費客戶端的 CPU 來請求大照片,然後將其調整到一定大小以將其推送到風景。 我們可以簡單地在 UPort 條件 URL 中動態指定一些參數,照片快取將自行調整照片的大小。 通常,它將選擇我們在磁碟上實際擁有的大小,盡可能接近請求的大小,並在特定座標中降價銷售。

順便說一下,我們公開了過去五年高負載系統開發者大會的視訊記錄 高負載++。 觀看、學習、分享和訂閱 YouTube 頻道.

我們還可以在那裡添加很多產品邏輯。 例如,我們可以使用URL參數添加不同的浮水印,我們可以對照片進行模糊、模糊或像素化。 這是當我們想要展示一個人的照片,但又不想展示他的臉時,這個效果很好,都在這裡實現了。

我們得到了什麼? 我們獲得了三個存在點、良好的技巧率,同時這些機器上沒有空閒的 CPU。 當然,他現在變得比以前更重要了。 我們需要給自己更強大的汽車,但這是值得的。

這涉及照片的歸還。 這裡的一切都非常清楚和明顯。 我想我沒有發現美國,幾乎所有的CDN都是這樣運作的。

而且,最有可能的是,經驗豐富的聽眾可能會有一個問題:為什麼不將所有內容都更改為 CDN? 情況大致相同;所有現代 CDN 都可以做到這一點。 原因有很多。

首先是照片。

Badoo 中儲存與分享照片的架構

這是我們基礎設施的關鍵點之一,我們需要對其進行盡可能多的控制。 如果這是來自第三方供應商的某種解決方案,並且您對其沒有任何權力,那麼當您擁有大型資料集並且擁有非常大的流量時,您將很難接受它用戶請求。

讓我舉一個例子。 現在,有了我們的基礎設施,相對而言,我們可以在出現一些問題或地下敲擊時,到機器那裡去搞亂。 我們可以添加一些我們只需要的指標的集合,我們可以以某種方式進行實驗,看看這如何影響圖表,等等。 現在正在這個快取叢集上收集大量統計資料。 我們會定期查看它並花很長時間探索一些異常現象。 如果是在CDN側,那就更難控制了。 或者,例如,如果發生某種事故,我們知道發生了什麼,我們知道如何忍受它以及如何克服它。 這是第一個結論。

第二個結論也比較具有歷史性,因為系統已經發展了很長一段時間,不同階段有很多不同的業務需求,並不總是符合CDN的概念。

上一點的結論是

Badoo 中儲存與分享照片的架構

這是因為在照片快取上我們有很多特定的邏輯,不能總是根據請求添加。 任何 CDN 都不可能根據您的要求為您添加一些自訂內容。 例如,如果您不希望客戶端能夠變更某些內容,請加密 URL。 是否要更改伺服器上的 URL 並對其進行加密,然後在此處發送一些動態參數。

這顯示什麼結論? 就我們而言,CDN 並不是一個很好的選擇。

Badoo 中儲存與分享照片的架構

就您而言,如果您有任何特定的業務需求,那麼您可以輕鬆實現我自己向您展示的內容。 這將與類似的負載曲線完美配合。

但如果您有某種通用解決方案,而且任務不是很具體,那麼您絕對可以安全地採用 CDN。 或者,時間和資源對您來說是否比控制更重要。

Badoo 中儲存與分享照片的架構

現代 CDN 幾乎擁有我現在告訴你的一切。 除了增加或減少某些功能外。

這是關於贈送照片。

現在讓我們回顧一下並討論一下儲存。

2013年即將過去。

Badoo 中儲存與分享照片的架構

新增了快取伺服器,效能問題就消失了。 一切都好。 數據集正在增長。 截至 2013 年,我們有大約 80 台伺服器連接到存儲,每個 DC 中有大約 40 台快取伺服器。 每個 DC 上的資料量為 560 TB,即總計約 PB。

Badoo 中儲存與分享照片的架構

而隨著資料集的成長,營運成本開始大幅上升。 這是什麼意思?

Badoo 中儲存與分享照片的架構

在這張繪製的圖中 - 使用 SAN、連接到它的機器和快取 - 有很多故障點。 如果我們之前已經處理過快取伺服器的故障,那麼一切或多或少都是可預測和可以理解的,但在儲存方面,一切都更糟。

首先,儲存區域網路 (SAN) 本身可能會發生故障。

其次,它透過光學連接到終端機器。 光卡和火星塞可能有問題。

Badoo 中儲存與分享照片的架構

當然,它們的數量不如 SAN 本身那麼多,但儘管如此,這些也是故障點。

接下來是機器本身,它連接到儲存。 它也可能會失敗。

Badoo 中儲存與分享照片的架構

總的來說,我們有三個失敗點。

此外,除了故障點之外,儲存本身的維護也很繁重。

這是一個複雜的多組件系統,系統工程師可能很難使用它。

最後也是最重要的一點。 如果這三點中的任何一個失敗,我們就有非零的機會失去用戶數據,因為檔案系統可能會崩潰。

Badoo 中儲存與分享照片的架構

假設我們的檔案系統損壞了。 首先,它的恢復需要很長時間——如果資料量很大,可能需要一周的時間。 其次,最終我們很可能會得到一堆難以理解的文件,需要以某種方式組合到使用者照片中。 我們還面臨著遺失資料的風險。 風險相當高。 而且這種情況發生的次數越多,整個鏈條中出現的問題越多,這種風險就越高。

必須對此採取一些措施。 我們決定只需要備份資料。 這實際上是一個顯而易見的解決方案,也是一個很好的解決方案。 我們做了什麼?

Badoo 中儲存與分享照片的架構

這是我們的伺服器之前連接到儲存的樣子。 這是一個主要部分,它只是一個塊設備,實際上代表透過光學進行遠端儲存的安裝座。

我們剛剛新增了第二部分。

Badoo 中儲存與分享照片的架構

我們在它旁邊放置了第二個儲存空間(幸運的是,它的錢並沒有那麼貴),並將其稱為備份分區。 它也透過光學連接並位於同一台機器上。 但我們需要以某種方式同步它們之間的資料。

這裡我們只是就近做一個非同步隊列。

Badoo 中儲存與分享照片的架構

她不是很忙。 我們知道我們沒有足夠的記錄。 佇列只是 MySQL 中的一個表,其中寫入諸如“您需要備份這張照片”之類的行。 對於任何變更或上傳,我們都會使用非同步或某種後台工作人員從主分割區複製到備份。

因此我們總是有兩個一致的部分。 即使該系統的一部分發生故障,我們也可以隨時透過備份更改主分割區,一切都會繼續運作。

但也因為如此,閱讀負荷大大增加,因為… 除了從主要部分閱讀的客戶之外,因為他們首先查看那裡的照片(那裡是最近的),然後在備份中查找它,如果他們沒有找到它(但 NGINX 就是這麼做的),我們的系統也是一個加備份,現在從主分割區讀取。 這並不是說這是一個瓶頸,但我本質上不想增加負載,就像這樣。

我們新增了第三個磁碟,這是一個小型 SSD,並將其稱為緩衝區。

Badoo 中儲存與分享照片的架構

現在如何運作。

使用者將照片上傳到緩衝區,然後將一個事件丟到佇列中,指示需要將其複製到兩個部分。 它被複製,並且照片在緩衝區中保存一段時間(例如一天),然後才從那裡清除。 這大大提高了用戶體驗,因為用戶上傳照片後,通常請求會立即開始跟進,或者他自己更新頁面並刷新。 但這完全取決於上傳的應用程式。

或者,例如,他開始向其他人展示自己的人在這張照片之後立即發送請求。 它尚未在快取中;第一個請求發生得非常快。 本質上與照片快取相同。 慢儲存根本不參與其中。 當它在一天後被清除時,它要么已經緩存在我​​們的快取層上,要么很可能沒有人再需要它了。 那些。 由於如此簡單的操作,這裡的使用者體驗得到了很好的發展。

嗯,最重要的是:我們不再丟失資料。

Badoo 中儲存與分享照片的架構

就說我們停了下來 潛在地 丟失數據,因為我們並沒有真正丟失它。 但有危險。 我們看到這個解決方案當然是好的,但它有點像是消除問題的症狀,而不是徹底解決問題。 一些問題仍然存在。

首先,這是運行所有這些機器的實體主機本身的一個故障點;它並沒有消失。

Badoo 中儲存與分享照片的架構

其次,SAN仍存在問題,維護工作量大等問題仍然存在。 這並不是說它是一個關鍵因素,但我想嘗試以某種方式在沒有它的情況下生活。

我們製作了第三個版本(實際上是第二個版本)——保留版本。 它看起來像什麼?

原來是這樣的——

Badoo 中儲存與分享照片的架構

我們的主要問題在於這是一個實體主機。

首先,我們正在刪除 SAN,因為我們想要進行實驗,我們想要嘗試僅本地硬碟。

Badoo 中儲存與分享照片的架構

這已經是2014-2015年了,那時磁碟及其在一台主機上的容量的情況變得好多了。 我們決定為什麼不嘗試。

然後我們只需將備份分區物理轉移到一台單獨的機器上即可。

Badoo 中儲存與分享照片的架構

這樣,我們就得到這張圖了。 我們有兩輛車儲存相同的資料集。 它們完全相互備份,並透過同一個MySQL中的非同步佇列透過網路同步資料。

Badoo 中儲存與分享照片的架構

為什麼這很有效,因為我們的記錄很少。 那些。 如果寫作與閱讀相當,也許我們會遇到某種網路開銷和問題。 很少寫作,大量閱讀——這種方法效果很好,即我們很少在這兩個伺服器之間複製照片。

如果您更詳細地了解一下,這是如何工作的。

Badoo 中儲存與分享照片的架構

上傳。 平衡器只需選擇具有一對的隨機主機並上傳到它。 同時,他自然會進行健康檢查並確保汽車不會掉下來。 那些。 他只將照片上傳到即時伺服器,然後透過非同步佇列將其全部複製到他的鄰居。 透過上傳,一切都變得非常簡單。

任務有點困難。

Badoo 中儲存與分享照片的架構

Lua 在這裡幫助了我們,因為在普通 NGINX 上很難實現這樣的邏輯。 我們首先向第一台伺服器發出請求,查看照片是否在那裡,因為它可能會上傳到例如鄰居,但尚未到達這裡。 如果有照片就好了。 我們立即將其提供給客戶端,並可能將其快取。

Badoo 中儲存與分享照片的架構

如果不存在,我們只需向我們的鄰居發出請求,並保證從那裡收到它。

Badoo 中儲存與分享照片的架構

那。 我們可以再次說:性能可能存在問題,因為存在不斷的往返 - 照片已上傳,但它不在這裡,我們正在發出兩個請求而不是一個,這應該會緩慢進行。

在我們的情況下,這並不緩慢。

Badoo 中儲存與分享照片的架構

我們在這個系統上收集了一堆指標,這個機制的條件智能率大約是95%。 那些。 這個備份的延遲很小,因此我們幾乎可以保證,照片上傳後,我們會第一時間拍攝,而不必兩次去任何地方。

那我們還有什麼真的很酷的呢?

以前,我們有主備份分割區,我們按順序讀取它們。 那些。 我們總是先搜尋主資料庫,然後再搜尋備份資料庫。 這是一舉一動。

現在我們同時利用兩台機器的讀取。 我們使用循環法來分發請求。 在一小部分情況下,我們會提出兩個請求。 但總體而言,我們現在的閱讀量是以前的兩倍。 而且發送機器和直接儲存機器上的負載都大大減少了,我們當時也有這樣的負載。

至於容錯。 其實我們主要是為了這個而奮鬥。 有了容錯能力,這裡一切都很好。

Badoo 中儲存與分享照片的架構

一輛車壞了。

Badoo 中儲存與分享照片的架構

沒問題! 系統工程師可能晚上都起不來,等到早上,不會有什麼不好的事情發生。

如果即使這台機器出現故障,隊列亂了,也沒有問題,日誌會先在活的機器上累積,然後添加到隊列中,然後再添加到要運行的車上。一段時間後即可投入運行。

Badoo 中儲存與分享照片的架構

維護也是如此。 我們只需關閉其中一台機器,手動將其從所有池中拉出,它停止接收流量,我們進行某種維護,編輯一些內容,然後將其返回服務,並且此備份很快就能趕上。 那些。 每天,一輛車的停機時間會在幾分鐘內趕上。 這實在是太少了。 有了容錯能力,我再說一遍,這裡一切都很酷。

從這個冗餘方案可以得到什麼結論?

我們獲得了容錯能力。

便於使用。 由於機器具有本機硬碟,因此從操作角度來看,這對於使用它的工程師來說要方便得多。

我們獲得了雙倍的閱讀津貼。

這是除了容錯之外的一個非常好的加分。

但也存在問題。 現在我們對與此相關的一些功能進行了更複雜的開發,因為系統已經變得 100% 最終一致。

Badoo 中儲存與分享照片的架構

例如,在某些後台工作中,我們必須不斷地思考:“我們現在在什麼伺服器上運行?”、“這裡真的有當前照片嗎?” ETC。 當然,這一切都是封裝起來的,對於編寫業務邏輯的程式設計師來說,它是透明的。 但是,儘管如此,這個巨大的複雜層已經出現了。 但我們已經準備好忍受這一點,以換取我們從中獲得的好處。

這裡又出現了一些衝突。

我一開始就說過,將所有內容儲存在本機硬碟上是不好的。 現在我說我們喜歡它。

是的,確實,隨著時間的推移,情況發生了很大的變化,現在這種做法有許多優點。 首先,我們的操作變得更加簡單。

其次,它的生產力更高,因為我們沒有這些自動控制器或與磁碟架的連接。

那裡有大量的機器,而這些只是在機器上組裝成一個raid的幾個磁碟。

但也有缺點。

Badoo 中儲存與分享照片的架構

即使以今天的價格,這也比使用 SAN 貴約 1,5 倍。 因此,我們決定不再大膽地將整個大型集群改裝為具有本地硬碟的汽車,並決定留下混合解決方案。

我們一半的機器使用硬碟(好吧,不是一半 - 可能是 30%)。 其餘的都是以前有優先預訂計畫的老車。 我們只是重新安裝它們,因為我們不需要新資料或其他任何東西,我們只是將安裝從一台實體主機移至兩台。

我們現在有大量的閱讀材料,並且我們擴大了它。 如果之前我們在一台機器上安裝了一個存儲,那麼現在我們在一對機器上安裝四個存儲。 而且效果很好。

讓我們簡單總結一下我們所取得的成就、我們為之奮鬥的目標以及我們是否成功。

結果

我們的用戶數高達 33 萬。

我們有三個辦事處 - 布拉格、邁阿密、香港。

它們包含一個快取層,由具有快速本地磁碟 (SSD) 的汽車組成,NGINX 的簡單機械、其 access.log 和 Python 守護程序在其上運行,處理所有這些並管理快取。

如果您願意,您在您的專案中,如果照片對您來說不像對我們那麼重要,或者如果權衡控制與開發速度和資源成本對您來說是相反的方向,那麼您可以安全地替換它有了CDN,現代CDN 就做得很好了。

接下來是儲存層,在該層上我們有相互備份的成對機器集群,只要檔案發生變化,檔案就會從一台機器非同步複製到另一台機器。

此外,其中一些機器可以使用本機硬碟。

其中一些機器連接到 SAN。

Badoo 中儲存與分享照片的架構

而且,一方面,它使用起來更方便,生產效率更高一些,另一方面,它在放置密度和每 GB 價格方面也很方便。

這是我們所獲得的架構及其發展方式的簡要概述。

船長還有一些提示,非常簡單。

首先,如果您突然決定迫切需要改進照片基礎設施中的所有內容,請先進行測量,因為也許沒有任何內容需要改進。

Badoo 中儲存與分享照片的架構

讓我舉一個例子。 我們有一組機器,可以從聊天中的附件中發送照片,該計劃自 2009 年以來一直在那裡運行,沒有人受到影響。 每個人都很好,每個人都喜歡一切。

為了衡量,先掛一堆指標,看看它們,然後決定哪些是你不滿意的,哪些是需要改進的。 為了衡量這一點,我們有一個很酷的工具,叫做 Pinba。

它允許您從 NGINX 收集每個請求和回應代碼以及時間分佈的非常詳細的統計資料 - 無論您想要什麼。 它綁定到各種不同的分析系統,然後您可以精美地查看這一切。

首先我們測量它,然後我們改進它。

更遠。 我們用快取優化讀取,用分片優化寫入,但這是一個顯而易見的點。

Badoo 中儲存與分享照片的架構

更遠。 如果您剛開始建立系統,那麼最好將照片製作為不可變檔案。 因為您立即就失去了快取失效、邏輯如何找到照片的正確版本等一系列問題。

Badoo 中儲存與分享照片的架構

假設您上傳了一百個文件,然後對其進行旋轉,使其成為物理上不同的文件。 那些。 無需思考:現在我將節省一點空間,將其寫入同一個文件,更改版本。 這總是效果不佳,並且會在以後造成很多麻煩。

下一點。 關於動態調整大小。

以前,當用戶上傳照片時,我們立即針對各種場合、不同的客戶剪切一大堆尺寸,並將它們都放在磁碟上。 現在我們已經放棄這個了。

我們只留下了三種主要尺寸:小號、中號和大號。 我們只是簡單地縮小 Uport 要求的尺寸後面的所有其他尺寸,我們只需縮小尺寸並將其提供給用戶即可。

事實證明,這裡快取層的 CPU 比我們在每個儲存上不斷重新產生這些大小便宜得多。 假設我們想要新增一個新的,這將需要一個月的時間 - 到處運行一個腳本,可以整齊地完成所有這些操作,而不會破壞叢集。 那些。 如果您現在有機會選擇,最好製作盡可能少的實體尺寸,但至少有一些分佈是,例如,三個。 其他所有內容都可以使用現成的模組即時調整大小。 現在一切都變得非常簡單又方便。

而且增量非同步備份也不錯。

正如我們的實踐所表明的,該方案對於延遲複製已更改的檔案非常有效。

Badoo 中儲存與分享照片的架構

最後一點也很明顯。 如果你的基礎設施現在沒有這樣的問題,但是有一個東西可以壞掉,當它變得多一點的時候,它肯定會壞掉。 因此,最好提前考慮一下,不要遇到問題。 這就是我想說的話。

往來

» 博0rsh201
» Badoo 部落格

本報告是高負載系統開發人員會議上最好的演講之一的文字記錄 高負載++。 距離 HighLoad++ 2017 大會還有不到一個月的時間。

我們已經準備好了 會議日程目前,日程正在積極制定中。

今年我們繼續探討架構和擴充的主題:

我們也在開發高負載系統的線上培訓課程中使用其中一些材料 高負載指南 是一系列精選的信件、文章、資料、影片。 我們的教科書已包含 30 多種獨特的材料。 連接!

來源: www.habr.com

添加評論