什麼是一致性哈希?一致性哈希是如何工作的?如何設計一致性哈希?

来源:https://www.cnblogs.com/powerai/archive/2023/05/25/17433152.html
-Advertisement-
Play Games

如果你有 *n* 個緩存伺服器,一個常見的負載均衡方式是使用以下的哈希方法: *伺服器索引 = 哈希(鍵) % N*,其中 *N* 是伺服器池的大小。 讓我們通過一個例子來說明這是如何工作的。如表5-1所示,我們有4台伺服器和8個字元串鍵及其哈希值。 ![image-2023052022160981 ...


如果你有 n 個緩存伺服器,一個常見的負載均衡方式是使用以下的哈希方法:

伺服器索引 = 哈希(鍵) % N,其中 N 是伺服器池的大小。

讓我們通過一個例子來說明這是如何工作的。如表5-1所示,我們有4台伺服器和8個字元串鍵及其哈希值。

image-20230520221609818

為了獲取存儲某個鍵的伺服器,我們執行模運算 f(鍵) % 4。例如,哈希(鍵0) % 4 = 1 意味著客戶端必須聯繫伺服器1來獲取緩存的數據。圖5-1展示了基於表5-1的鍵的分佈。

image-20230520221627093

當伺服器池的大小固定且數據分佈均勻時,這種方法工作得很好。然而,當新的伺服器被添加,或者現有的伺服器被移除時,就會出現問題。例如,如果伺服器1離線,伺服器池的大小就變成了3。使用相同的哈希函數,我們得到的鍵的哈希值是相同的。但是應用模運算會因為伺服器數量減少了1而得到不同的伺服器索引。我們應用 哈希 % 3 得到的結果如表5-2所示:

image-20230520221638743

圖5-2展示了基於表5-2的新鍵分佈。

image-20230520221651912

如圖5-2所示,大多數鍵都被重新分配了,而不僅僅是那些最初存儲在離線伺服器(伺服器1)中的鍵。這意味著,當伺服器1離線時,大多數緩存客戶端將連接到錯誤的伺服器來獲取數據。這導致了一場緩存未命中的風暴。一致性哈希是一種有效的技術來緩解這個問題。

一致性哈希

引用自維基百科:"一致性哈希是一種特殊的哈希,使得當哈希表大小改變且使用一致性哈希時,平均只有 k/n 個鍵需要被重新映射,其中 k 是鍵的數量,n 是槽位的數量。相比之下,在大多數傳統哈希表中,數組槽位數量的變化導致幾乎所有的鍵都需要被重新映射[1]”。

哈希空間和哈希環

現在我們理解了一致性哈希的定義,讓我們瞭解它是如何工作的。假設使用SHA-1作為哈希函數f,哈希函數的輸出範圍是:x0, x1, x2, x3, ..., xn。在密碼學中,SHA-1的哈希空間從0到2^160 - 1。也就是說,x0 對應0,xn 對應2^160 - 1,所有其他的哈希值都落在0和2^160 - 1之間。圖5-3展示了哈希空間。

image-20230520221712073

通過連接兩端,我們得到一個如圖5-4所示的哈希環:

image-20230520221721241

哈希伺服器

使用相同的哈希函數f,我們根據伺服器的IP或名字將伺服器映射到環上。圖5-5顯示了4台伺服器被映射到哈希環上。

image-20230520221733973

哈希鍵

值得一提的是,這裡使用的哈希函數與“重哈希問題”中的不同,並且沒有模運算。如圖5-6所示,4個緩存鍵(key0,key1,key2和key3)被哈希到哈希環上。

image-20230520221804796

伺服器查找

為了確定一個鍵存儲在哪個伺服器上,我們從環上的鍵位置順時針方向進行尋找,直到找到一個伺服器。圖5-7解釋了這個過程。順時針方向,key 0 存儲在 server 0上;key1 存儲在 server 1 上;key2 存儲在 server 2 上;key3 存儲在 server 3 上。

image-20230520221817073

添加伺服器

使用上述邏輯,添加新伺服器只需要重新分配一部分鍵。

在圖5-8中,新增 server 4 後,只有 key0 需要被重新分配。k1, k2,k3 仍然在相同的伺服器上。讓我們仔細看看這個邏輯。在 server 4 添加之前,key0 存儲在 server 0 上。現在,key0 將存儲在 server 4 上,因為 server 4 是它從環上的 key0 位置順時針方向遇到的第一個伺服器。其他的鍵根據一致性哈希演算法不需要重新分配。

image-20230520221838084

移除伺服器

當伺服器被移除時,只有少部分的鍵需要通過一致性哈希進行重新分配。在圖5-9中,當 server 1 被移除時,只有 key1 必須被映射到 server 2。其餘的鍵不受影響。

image-20230520221851239

基本方法中的兩個問題

一致性哈希演算法是由MIT的Karger等人提出的[1]。基本步驟如下:

  • 使用均勻分佈的哈希函數將伺服器和鍵映射到環上。
  • 要找出鍵映射到哪個伺服器,從鍵位置開始順時針方向找到環上的第一個伺服器。

這種方法存在兩個問題。首先,考慮到伺服器可能會被添加或移除,不可能在環上為所有伺服器保持相同大小的分區。分區是相鄰伺服器之間的哈希空間。每個伺服器被分配到的環上的分區大小可能非常小或者相當大。在圖5-10中,如果s1被移除,s2的分區(雙向箭頭高亮表示)就是s0s3分區的兩倍大。

image-20230520221901282

第二,環上的鍵分佈可能非均勻。例如,如果伺服器映射到圖5-11中列出的位置,大部分的鍵都存儲在server 2上。然而,server 1server 3 沒有任何數據。

image-20230520221911034

一種被稱為虛擬節點或副本的技術被用來解決這些問題。

虛擬節點

虛擬節點是指實際節點,每個伺服器在環上都由多個虛擬節點表示。在圖5-12中,server 0server 1 都有3個虛擬節點。這個3是隨意選擇的;在實際系統中,虛擬節點的數量要多得多。我們不再使用 s0,而是使用 s0_0, s0_1s0_2 來在環上表示 server 0。同樣,s1_0, s1_1s1_2 在環上表示 server 1。有了虛擬節點,每個伺服器就負責多個分區。標簽為 s0 的分區(邊)由 server 0 管理。另一方面,標簽為 s1 的分區由 server 1 管理。

image-20230520221923607

要找出一個鍵存儲在哪個伺服器上,我們從鍵的位置順時針方向去找環上遇到的第一個虛擬節點。在圖5-13中,要找出k0存儲在哪個伺服器上,我們從k0的位置順時針方向找到虛擬節點s1_1,它指向server 1

image-20230520221943844

隨著虛擬節點數量的增加,鍵的分佈變得更加均衡。這是因為隨著虛擬節點數量的增加,標準差變得更小,導致數據分佈均衡。標準差衡量了數據的分散程度。線上研究的一項實驗結果[2]表明,當有一百或兩百個虛擬節點時,標準差在均值的5%(200個虛擬節點)到10%(100個虛擬節點)之間。當我們增加虛擬節點數量時,標準差會變小。然而,我們需要更多的空間來存儲虛擬節點的數據。這是一個權衡,我們可以調整虛擬節點的數量以適應我們的系統需求。

找到受影響的鍵

當添加或移除一個伺服器時,部分數據需要被重新分佈。我們如何找到受影響的範圍以重新分配鍵呢?

在圖5-14中,server 4被添加到環中。受影響的範圍從s4(新添加的節點)開始,逆時針移動到找到一個伺服器(s3)。因此,位於s3s4之間的鍵需要被重新分配給s4

image-20230520221954742

當一個伺服器(s1)如圖5-15所示被移除時,受影響的範圍從s1(被移除的節點)開始,逆時針繞環移動到找到一個伺服器(s0)。因此,位於s0s1之間的鍵必須被重新分配給s2

image-20230520222004501

總結

在這一章,我們深入討論了一致性哈希,包括為什麼需要它以及它是如何工作的。一致性哈希的好處包括:

  • 當伺服器被添加或移除時,最小化鍵的重新分佈。
  • 因為數據更均勻地分佈,所以易於橫向擴展。
  • 緩解熱點鍵問題。過度訪問特定的分片可能導致伺服器過載。想象一下,Katy Perry、Justin Bieber和Lady Gaga的數據全部都在同一個分片上。一致性哈希通過更均勻地分佈數據來緩解這個問題。

一致性哈希在現實世界的系統中被廣泛應用,包括一些著名的系統:

  • Amazon的Dynamo資料庫的分區組件 [3]
  • Apache Cassandra中跨集群的數據分區 [4]
  • Discord聊天應用 [5]
  • Akamai內容分髮網絡 [6]
  • Maglev網路負載均衡器 [7]

恭喜你走到這一步!現在給自己一個贊。幹得好!

參考資料

[1] 一致性哈希:https://en.wikipedia.org/wiki/Consistent_hashing

[2] 一致性哈希:

https://tom-e-white.com/2007/11/consistent-hashing.html

[3] Dynamo:亞馬遜的高可用鍵值存儲:
https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf

[4] Cassandra - 一個去中心化的結構化存儲系統:

http://www.cs.cornell.edu/Projects/ladis2009/papers/Lakshman-ladis2009.PDF

[5] 如何將Discord Elixir擴展到500萬併發用戶:
https://blog.discord.com/scaling-elixir-f9b8e1e7c29b

[6] CS168:現代演算法工具箱第一課:簡介和一致性哈希:http://theory.stanford.edu/~tim/s16/l/l1.pdf

[7] Maglev:一個快速可靠的軟體網路負載均衡器:
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44824.pdf


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Iframe是一個歷史悠久的HTML元素,根據MDN WEB DOCS官方介紹,Iframe定義為HTML內聯框架元素,表示嵌套的Browsing Context,它能夠將另一個HTML頁面嵌入到當前頁面中。Iframe可以廉價實現跨應用級的頁面共用,並且具有使用簡單、高相容性、內容隔離等優點,因此... ...
  • 比如老王我,用npm init新建一個包,改把改把,然後來個npm publish,so easy ✌️!Too young too naive, baby
  • 在 CSS 中,存在許多數學函數,這些函數能夠通過簡單的計算操作來生成某些屬性值,例如 : * calc():用於計算任意長度、百分比或數值型數據,並將其作為 CSS 屬性值。 * min() 和 max():用於比較一組數值中的最大值或最小值,也可以與任意長度、百分比或數值型數據一同使用。 * c ...
  • 1.轉換 轉換(transform)是CSS3中具有顛覆性的特征之一,可以實現元素的位移、旋轉、縮放等效果。 轉換(transform)可以簡單理解為變形。 移動:translate 旋轉:rotate 縮放:scale 1.1 二維坐標系 2D轉換是改變在二維平面上的位置和形狀的一種技術。 1.2 ...
  • > 隨著人工智慧技術的不斷發展,阿裡體育等IT大廠,推出的“樂動力”、“天天跳繩”AI運動APP,讓**雲上運動會、線上運動會、健身打卡、AI體育指導**等概念空前火熱。那麼,能否將這些在APP成功應用的場景搬上小程式,分享這些概念的紅利呢?本系列文章就帶您一步一步從零開始開發一個AI運動小程式,本 ...
  • 相信很多公司的前端開發人員都會選擇使用vue+element-ui的形式來開發公司的管理後臺系統,基於element-ui很豐富的組件生態,我們可以很快速的開發管理後臺系統的頁面(管理後臺系統的頁面也不複雜,大多都是分頁查詢類需求和增刪改查)。但一個前端框架有優點,就必然會有一些缺點或bug存在,e... ...
  • 寫這篇的目的是,今天在重新學習javascript時發現了HttpOnly這個標簽,所以專門的mark了下。 誰在什麼時候發明瞭HttpOnly 2002年微軟為ie6的sp1創造了HttpOnly 什麼是HttpOnly HttpOnly是包含在http返回頭Set-Cookie裡面的一個附加的f ...
  • 本文將學習如何使用滾動控制 ScrollControls 來控制模型的的動畫播放和相機動畫,通過滾動滑鼠滾輪或者上下移動觸摸板,來控制模型的動畫播放進度或者相機的方位視角,從而呈現出驚艷的視覺效果。通過本文的閱讀和案例頁面的實現,你將學習到的知識包括:R3F 生態中的 ScrollControls、... ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...