Google研究 | 使用一致的雜湊演算法分配臨界負載
文 | NYC 演算法團隊首席科學家 Vahab Mirrokni 和研究員 Morteza Zadimoghaddam
執行大規模網路服務(例如內容託管)離不開負載平衡,也就是將客戶端均勻地分配到多個伺服器上,使得每個伺服器都不至於過載。此外,在隨時可以新增或移除客戶端和伺服器的動態環境中,較為理想的做法是找到一種不會隨時間而大幅改變的分配方案。換而言之,我們需要在一段時間內一致地將客戶端分配到伺服器。
通過與哥本哈根大學客座研究員 Mikkel Thorup 合作,我們開發了一種全新而有效的分配演算法來解決這一問題,能夠嚴格保證每臺伺服器的最大負載,並從理論和實踐上研究了這一演算法。隨後,我們與我們的雲團隊合作,在 Google Cloud Pub/Sub 這一可擴充套件的事件流服務中實現了該演算法,我們發現,在符合一致性和穩定性目標的同時,還顯著改善了負載分配的均勻性(以伺服器分配到的最大負載來衡量)。2016 年 8 月,我們在“使用一致的雜湊演算法分配臨界負載”(Consistent Hashing with Bounded Loads) 論文中介紹了我們的演算法,並在 ArXiv 中分享了這一演算法,以供更廣泛的研究社群使用。
三個月以後,來自 Vimeo 的 Andrew Rodland 通知我們,他發現了該論文,隨後在 haproxy(一段廣泛使用的開放原始碼軟體)中實現了該演算法並將其用於 Vimeo 的負載平衡專案。結果非常引人注目:應用這些演算法幫助他們幾乎將快取頻寬降低到原來的 1/8,從而消除了擴充套件瓶頸。他最近在一篇博文中概述了這一案例,詳細介紹了他的用例。毋庸贅言,我們非常興奮地瞭解到,我們的理論研究成果不僅被投入應用,還體現出使用價值,並且還開放原始碼。
背景
儘管過去已經研發出一致的雜湊演算法理念來解決動態環境中的負載平衡問題,但所有之前開發的方案都存在一個根本性的問題:在特定的場景下,它們可能導致許多伺服器上的負載平衡不能達到最佳狀態。
此外,由於可能隨時新增或移除客戶端和伺服器,在做出此類改動時,我們不希望移動太多的客戶端。因此,動態分配演算法不僅必須始終確保正確的負載平衡,還應儘量減少每次對系統做出改動之後所移動的客戶端數量。當每臺伺服器的容量存在嚴格的限制時,也就是說,每臺伺服器都有嚴格的容量限制,負載不得超過此限制之時,此類分配問題會變得更為嚴峻。通常,我們希望容量接近於平均負載。
換而言之,我們希望在最終的分配中同時實現均勻性和一致性這兩大目標。對於伺服器集固定不變、只有客戶端集會更新這種簡單很多的情形,有大量的文獻介紹了相關的解決方案,但在本文中,我們討論的解決方案針對的是客戶端和伺服器均可隨時新增和移除的完全動態的情形。
演算法
我們可以將伺服器比作垃圾桶,將客戶端比作球,並借鑑將球隨機投入垃圾桶的過程 (balls-to-bins stochastic processes) 這一經過深入研究的模型,採用與之類似的抽象方法。均勻性目標要求所有垃圾桶所裝的球數量大致等於平均密度(球數除以箱子數)。對於引數 ε,我們將每個垃圾桶的容量設定為平均負載的最低或最高倍數 (1+ε)。這一額外的容量讓我們可以設計出一種能夠同時滿足均勻性目標和一致性目標的分配演算法。
設想給定範圍的一組數字,將其分佈到一個圓圈上。我們對球應用一個雜湊函式,對垃圾桶應用另一個不同的雜湊函式,以獲取該範圍內、與該圓圈上不同位置對應的數字。隨後,我們開始按特定的順序分配球,此順序與其雜湊值無關(假設基於其 ID)。然後,按順時針移動每個球並將其分配到第一個有空閒容量的垃圾桶。
我們分析一下上面的例子,我們使用兩種不同的雜湊函式,將 6 個球和 3 個垃圾桶隨機分配到圓圈上的不同位置。對於本例,我們假設每個垃圾桶的容量設定為 2。我們開始按 ID 值的升序分配球。1 號球按順時針移動,進入垃圾桶 C。2 號球進入垃圾桶 A。3 號和 4 號球進入垃圾桶 B。5 號球進入垃圾桶 C。6 號球順時針移動,首先命中垃圾桶 B。然而,垃圾桶 B 的容量為 2,而其中已經裝有 3 號和 4 號球。因此,6 號球繼續向前移動,直至到達垃圾桶 C,但該垃圾桶也已滿。最後,6 號球進入仍有空餘位置的垃圾桶 A。
如對系統進行任何更新(插入/刪除球或垃圾桶),則會重新計算分配,以保持均勻性目標。分析表明小幅更新(插入和刪除少量的球或垃圾桶)會導致分配狀態的小幅改變,因此,可滿足一致性目標。在我們的論文中,我們展示了在該系統中,每插入或移除一個球將會導致其他球進行 O(1/ε2) 次運動。最重要的是,此上限與系統中球或垃圾桶的總數無關。因此,如果球或垃圾桶的數量加倍,此上限不會改變。上限與球或垃圾桶的數量無關,為可伸縮性帶來了巨大的空間,因為我們將其搬到更大的例項中,仍然可以滿足一致性目標。下面顯示了更新某個垃圾桶/伺服器時,每次更新所導致的移動(重新分配)次數模擬結果。
紅色曲線代表移動的平均次數,藍色柱線代表不同 ε 值(X 軸)的方差。虛線代表我們的理論結果所建議的上限,其非常適合用於預測實際的移動次數。此外,對於任何 ε 值,我們知道,每個垃圾桶的負載至多是平均負載的 (1+ε) 倍。下面,我們看到不同值 ε=0.1、ε=0.3 和 ε=0.9 條件下垃圾桶的負載分佈情況。
▲ 不同 ε 值下的負載分佈。對於所有範圍的負載(從 0 到 (1+ε) 倍於平均負載),負載分佈均接近均勻,許多垃圾桶的負載等於平均負載的 (1+ε) 倍。
我們可以看到,這裡需要折中考慮,較低的 ε 值有利於確保均勻性,但不利於確保一致性,而較大的 ε 值則有利於確保一致性。較低的 ε 值可確保許多負載等於平均負載的 (1+ε) 倍這一硬性容量限制,而其他負載則為遞減分佈。
在提供內容託管服務時,必須做好應對許多不同特性的例項的準備。這種一致的雜湊方案非常適合此類情形,因為即便是最糟糕的情形下,它也能有不錯的表現。
我們的內部研究結果激動人心,我們更欣慰的是,更廣大的社群發現我們的解決方案非常有用,足以列入開放原始碼,讓任何人都可以使用該演算法:
https://github.com/arodland/haproxy
如果您有興趣進一步瞭解本研究的詳細情況,請在 ArXiv 上查閱此論文,並請務必關注,NYC 演算法團隊將公佈更多的研究成果:
https://arxiv.org/abs/1608.01350
致謝:
我們想感謝來自 Google Cloud Pub/Sub 團隊的 Alex Totok、Matt Gruskin、Sergey Kondratyev 和 Haakon Ringberg,當然還要感謝 Mikkel Thorup 對此論文做出的寶貴貢獻。
瞭解更多細節,檢視文內所有連結,請點選文末“閱讀原文”。
點選「閱讀原文」,檢視文內連結
相關文章
- 一致性雜湊負載均衡演算法的探討負載演算法
- 對一致性雜湊演算法的深入研究演算法
- 一致性雜湊演算法演算法
- Talos網路卡負載最佳化:基於個性化一致性雜湊的負載均衡負載
- 你知道雜湊演算法,但你知道一致性雜湊嗎?演算法
- 動手實現一致性雜湊演算法,並搭建環境測試其負載均衡特性.演算法負載
- Dubbo一致性雜湊負載均衡的原始碼和Bug,瞭解一下?負載原始碼
- 一致性雜湊演算法 PHP 實現演算法PHP
- 一致性雜湊演算法原理設計演算法
- PHP實現一致性雜湊演算法(轉的)PHP演算法
- doublejump - 又快又簡潔的一致性雜湊庫,Google Jump 演算法的改進版Go演算法
- 5分鐘理解一致性雜湊演算法演算法
- 五分鐘看懂一致性雜湊演算法演算法
- [Redis]一致性雜湊Redis
- 分散式系統中一致性雜湊演算法分散式演算法
- 3.1 雜湊演算法演算法
- 一致性雜湊演算法(consistent hashing)【轉】演算法
- 分散式資料快取中的一致性雜湊演算法分散式快取演算法
- 雜湊技術【雜湊表】查詢演算法 PHP 版演算法PHP
- Redis中的一致性雜湊問題Redis
- js 雜湊雜湊值的模組JS
- 淺析雜湊演算法演算法
- 雜湊演算法簡介演算法
- 雜湊查詢演算法演算法
- 超酷演算法:同型雜湊演算法
- 【六褘-Java】雜湊演算法記憶體圖;set集合低層採用雜湊表儲存元素;雜湊演算法的流程Java演算法記憶體
- 一致性雜湊演算法及其在分散式系統中的應用演算法分散式
- 演算法學習-雜湊表演算法
- 22 | 雜湊演算法(下):雜湊演算法在分散式系統中有哪些應用?演算法分散式
- 全面瞭解一致性雜湊演算法及PHP程式碼實現演算法PHP
- 五分鐘理解一致性雜湊演算法(consistent hashing)演算法
- mysql中雜湊索引的使用限制MySql索引
- Fortran雜湊函式庫的使用函式
- 雜湊表(雜湊表)詳解
- NGINX負載均衡的四種分配方式Nginx負載
- 【資料結構與演算法學習】雜湊表(Hash Table,雜湊表)資料結構演算法
- 查詢演算法及雜湊表演算法
- MD5雜湊加密演算法加密演算法