22 | 雜湊演算法(下):雜湊演算法在分散式系統中有哪些應用?
上一節,我講了雜湊演算法的四個應用,它們分別是:安全加密、資料校驗、唯一標識、雜湊函式。今天,我們再來看剩餘三種應用:負載均衡、資料分片、分散式儲存。
你可能已經發現,這三個應用都跟分散式系統有關。沒錯,今天我就帶你看下,雜湊演算法是如何解決這些分散式問題的。
應用五:負載均衡
我們知道,負載均衡演算法有很多,比如輪詢、隨機、加權輪詢等。那如何才能實現一個會話粘滯(session sticky)的負載均衡演算法呢?也就是說,我們需要在同一個客戶端上,在一次會話中的所有請求都路由到同一個伺服器上。
最直接的方法就是,維護一張對映關係表,這張表的內容是客戶端 IP 地址或者會話 ID 與伺服器編號的對映關係。客戶端發出的每次請求,都要先在對映表中查詢應該路由到的伺服器編號,然後再請求編號對應的伺服器。這種方法簡單直觀,但也有幾個弊端:
- 如果客戶端很多,對映表可能會很大,比較浪費記憶體空間;
- 客戶端下線、上線,伺服器擴容、縮容都會導致對映失效,這樣維護對映表的成本就會很大;
如果藉助雜湊演算法,這些問題都可以非常完美地解決。我們可以通過雜湊演算法,對客戶端 IP 地址或者會話 ID 計算雜湊值,將取得的雜湊值與伺服器列表的大小進行取模運算,最終得到的值就是應該被路由到的伺服器編號。 這樣,我們就可以把同一個 IP 過來的所有請求,都路由到同一個後端伺服器上。
應用六:資料分片
雜湊演算法還可以用於資料的分片。我這裡有兩個例子。
- 如何統計“搜尋關鍵詞”出現的次數?
假如我們有 1T 的日誌檔案,這裡面記錄了使用者的搜尋關鍵詞,我們想要快速統計出每個關鍵詞被搜尋的次數,該怎麼做呢?
我們來分析一下。這個問題有兩個難點,第一個是搜尋日誌很大,沒辦法放到一臺機器的記憶體中。第二個難點是,如果只用一臺機器來處理這麼巨大的資料,處理時間會很長。
針對這兩個難點,我們可以先對資料進行分片,然後採用多臺機器處理的方法,來提高處理速度。具體的思路是這樣的:為了提高處理的速度,我們用 n 臺機器並行處理。我們從搜尋記錄的日誌檔案中,依次讀出每個搜尋關鍵詞,並且通過雜湊函式計算雜湊值,然後再跟 n 取模,最終得到的值,就是應該被分配到的機器編號。
這樣,雜湊值相同的搜尋關鍵詞就被分配到了同一個機器上。也就是說,同一個搜尋關鍵詞會被分配到同一個機器上。每個機器會分別計算關鍵詞出現的次數,最後合併起來就是最終的結果。
實際上,這裡的處理過程也是 MapReduce 的基本設計思想。
- 如何快速判斷圖片是否在相簿中?
如何快速判斷圖片是否在相簿中?上一節我們講過這個例子,不知道你還記得嗎?當時我介紹了一種方法,即給每個圖片取唯一標識(或者資訊摘要),然後構建雜湊表。
假設現在我們的相簿中有 1 億張圖片,很顯然,在單臺機器上構建雜湊表是行不通的。因為單臺機器的記憶體有限,而 1 億張圖片構建雜湊表顯然遠遠超過了單臺機器的記憶體上限。
我們同樣可以對資料進行分片,然後採用多機處理。我們準備 n 臺機器,讓每臺機器只維護某一部分圖片對應的雜湊表。我們每次從相簿中讀取一個圖片,計算唯一標識,然後與機器個數 n 求餘取模,得到的值就對應要分配的機器編號,然後將這個圖片的唯一標識和圖片路徑發往對應的機器構建雜湊表。
當我們要判斷一個圖片是否在相簿中的時候,我們通過同樣的雜湊演算法,計算這個圖片的唯一標識,然後與機器個數 n 求餘取模。假設得到的值是 k,那就去編號 k 的機器構建的雜湊表中查詢。
現在,我們來估算一下,給這 1 億張圖片構建雜湊表大約需要多少臺機器。
雜湊表中每個資料單元包含兩個資訊,雜湊值和圖片檔案的路徑。假設我們通過 MD5 來計算雜湊值,那長度就是 128 位元,也就是 16 位元組。檔案路徑長度的上限是 256 位元組,我們可以假設平均長度是 128 位元組。如果我們用連結串列法來解決衝突,那還需要儲存指標,指標只佔用 8 位元組。所以,雜湊表中每個資料單元就佔用 152 位元組(這裡只是估算,並不準確)。
假設一臺機器的記憶體大小為 2GB,雜湊表的裝載因子為 0.75,那一臺機器可以給大約 1000 萬(2GB*0.75/152)張圖片構建雜湊表。所以,如果要對 1 億張圖片構建索引,需要大約十幾臺機器。在工程中,這種估算還是很重要的,能讓我們事先對需要投入的資源、資金有個大概的瞭解,能更好地評估解決方案的可行性。
實際上,針對這種海量資料的處理問題,我們都可以採用多機分散式處理。藉助這種分片的思路,可以突破單機記憶體、CPU 等資源的限制。
應用七:分散式儲存
現在網際網路面對的都是海量的資料、海量的使用者。我們為了提高資料的讀取、寫入能力,一般都採用分散式的方式來儲存資料,比如分散式快取。我們有海量的資料需要快取,所以一個快取機器肯定是不夠的。於是,我們就需要將資料分佈在多臺機器上。
該如何決定將哪個資料放到哪個機器上呢?我們可以借用前面資料分片的思想,即通過雜湊演算法對資料取雜湊值,然後對機器個數取模,這個最終值就是應該儲存的快取機器編號。
但是,如果資料增多,原來的 10 個機器已經無法承受了,我們就需要擴容了,比如擴到 11 個機器,這時候麻煩就來了。因為,這裡並不是簡單地加個機器就可以了。
原來的資料是通過與 10 來取模的。比如 13 這個資料,儲存在編號為 3 這臺機器上。但是新加了一臺機器中,我們對資料按照 11 取模,原來 13 這個資料就被分配到 2 號這臺機器上了。
因此,所有的資料都要重新計算雜湊值,然後重新搬移到正確的機器上。這樣就相當於,快取中的資料一下子就都失效了。所有的資料請求都會穿透快取,直接去請求資料庫。這樣就可能發生雪崩效應,壓垮資料庫。
所以,我們需要一種方法,使得在新加入一個機器後,並不需要做大量的資料搬移。這時候,一致性雜湊演算法就要登場了。
假設我們有 k 個機器,資料的雜湊值的範圍是[0, MAX]。我們將整個範圍劃分成 m 個小區間(m 遠大於 k),每個機器負責 m/k 個小區間。當有新機器加入的時候,我們就將某幾個小區間的資料,從原來的機器中搬移到新的機器中。這樣,既不用全部重新雜湊、搬移資料,也保持了各個機器上資料數量的均衡。
一致性雜湊演算法的基本思想就是這麼簡單。除此之外,它還會藉助一個虛擬的環和虛擬結點,更加優美地實現出來。這裡我就不展開講了,如果感興趣,你可以看下這個介紹。
除了我們上面講到的分散式快取,實際上,一致性雜湊演算法的應用非常廣泛,在很多分散式儲存系統中,都可以見到一致性雜湊演算法的影子。
解答開篇 & 內容小結
這兩節的內容理論不多,比較貼近具體的開發。今天我講了三種雜湊演算法在分散式系統中的應用,它們分別是:負載均衡、資料分片、分散式儲存。
在負載均衡應用中,利用雜湊演算法替代對映表,可以實現一個會話粘滯的負載均衡策略。在資料分片應用中,通過雜湊演算法對處理的海量資料進行分片,多機分散式處理,可以突破單機資源的限制。在分散式儲存應用中,利用一致性雜湊演算法,可以解決快取等分散式系統的擴容、縮容導致資料大量搬移的難題。
課後思考
這兩節我總共講了七個雜湊演算法的應用。實際上,我講的也只是冰山一角,雜湊演算法還有很多其他的應用,比如網路協議中的 CRC 校驗、Git commit id 等等。除了這些,你還能想到其他用到雜湊演算法的地方嗎?
相關文章
- 一致性雜湊演算法及其在分散式系統中的應用演算法分散式
- 分散式系統中一致性雜湊演算法分散式演算法
- 3.1 雜湊演算法演算法
- 雜湊技術【雜湊表】查詢演算法 PHP 版演算法PHP
- 雜湊表應用
- 淺析雜湊演算法演算法
- 雜湊查詢演算法演算法
- 雜湊演算法簡介演算法
- Hash,雜湊,雜湊?
- 【六褘-Java】雜湊演算法記憶體圖;set集合低層採用雜湊表儲存元素;雜湊演算法的流程Java演算法記憶體
- 雜湊函式函式
- 七夕也要學起來,雜湊雜湊雜湊!
- 【資料結構與演算法學習】雜湊表(Hash Table,雜湊表)資料結構演算法
- 你知道雜湊演算法,但你知道一致性雜湊嗎?演算法
- MD5雜湊加密演算法加密演算法
- 查詢演算法及雜湊表演算法
- 雜湊
- 什麼是雜湊演算法?雜湊競猜遊戲開發原理詳解演算法遊戲開發
- 雜湊表(雜湊表)原理詳解
- 【尋跡#3】 雜湊與雜湊表
- js 雜湊雜湊值的模組JS
- 雜湊遊戲系統丨雜湊遊戲系統開發(演示版)丨雜湊遊戲開發原始碼及案例遊戲開發原始碼
- 分散式資料快取中的一致性雜湊演算法分散式快取演算法
- 雜湊索引索引
- 樹雜湊
- 2024.3.26 雜湊
- 雜湊碰撞
- 字串雜湊字串
- 雜湊表
- 雜湊對映用法及演算法例題演算法
- 演算法與資料結構——雜湊表演算法資料結構
- RIPEMD演算法:多功能雜湊演算法的瑰寶演算法
- 雜湊競猜遊戲開發示例丨Hash雜湊遊戲系統開發丨雜湊競猜遊戲詳情遊戲開發
- Hash雜湊遊戲原始碼丨雜湊競猜遊戲系統技術開發丨Hash雜湊遊戲講解遊戲原始碼
- 雜湊遊戲原始碼開發搭建丨hash雜湊遊戲競猜原始碼搭建丨雜湊遊戲系統開發遊戲原始碼
- 雜湊競猜開發原理丨雜湊競猜遊戲原始碼丨雜湊競猜系統開發設計程式碼遊戲原始碼
- HASH雜湊遊戲原始碼丨HASH雜湊遊戲系統開發丨HASH雜湊遊戲開發成品原始碼部署原始碼遊戲開發
- 雜湊資料結構以及在HashMap中的應用資料結構HashMap