《演算法與資料結構》學習筆記18 雜湊演算法

2021-09-11 04:28:22 字數 4258 閱讀 7546

啊,繼續學習之旅。

前面幾篇提到「雜湊表」「雜湊函式」,這裡又講到「雜湊演算法」,是不是有點一頭霧水?實際上,不管是「雜湊」還是「雜湊」,這都是中文翻譯的差別,英文其實就是「hash」。所以,常聽到有人把「雜湊表」叫作「雜湊表」「hash 表」,把「雜湊演算法」叫作「hash 演算法」或者「雜湊演算法」。

什麼是雜湊演算法?

將任意長度的二進位制值串對映為固定長度的二進位制值串,這個對映的規則就是雜湊演算法,而通過原始資料對映之後得到的二進位制值串就是雜湊值。但是,要想設計乙個優秀的雜湊演算法並不容易,有幾點要求需要滿足:

以md5為例,說明一下:

分別對「《今天我來講雜湊演算法》」和「《jiajia》」這兩個文字,計算 md5 雜湊值,得到兩串看起來毫無規律的字串(md5 的雜湊值是 128 位的 bit 長度,為了方便表示,把它們轉化成了 16 進製編碼)。可以看出來,無論要雜湊的文字有多長、多短,通過 md5 雜湊之後,得到的雜湊值的長度都是相同的,而且得到的雜湊值看起來像一堆隨機數,完全沒有規律。

md5

(" 今天我來講雜湊演算法 "

)= bb4767201ad42c74e650c1b6c03d78fa

md5(

"jiajia"

)= cd611a31ea969b908932d44d126d195b

再來看兩個非常相似的文字,「《我今天講雜湊演算法!》」和「《我今天講雜湊演算法》」。這兩個文字只有乙個感嘆號的區別。如果用 md5 雜湊演算法分別計算它們的雜湊值,儘管只有一字之差,得到的雜湊值也是完全不同的。

md5

(" 我今天講雜湊演算法!")=

425f

0d5a917188d2c3c3dc85b5e4f2cb

md5(

" 我今天講雜湊演算法 "

)= a1fb91ac128e6aa37fe42c663971ac3d

雜湊演算法要處理的文字可能是各種各樣的。比如,對於非常長的文字,如果雜湊演算法的計算時間很長,那就只能停留在理論研究的層面,很難應用到實際的軟體開發中。雜湊演算法的應用非常非常多,這裡列舉七個,分別是安全加密、唯一標識、資料校驗、雜湊函式、負載均衡、資料分片、分布式儲存。

應用一:安全加密

最常用於加密的雜湊演算法是md5(md5 message-digest algorithm,md5 訊息摘要演算法)和sha(secure hash algorithm,安全雜湊演算法),還有des(data encryption standard,資料加密標準)、aes(advanced encryption standard,高階加密標準)。

在前面提到的雜湊演算法四點要求中,對用於加密的雜湊演算法來說,有兩點格外重要。第一點是很難根據雜湊值反向推導出原始資料,第二點是雜湊衝突的概率要很小。

對於第一點,加密的目的就是防止原始資料洩露,所以很難通過雜湊值反向推導原始資料,這是乙個最基本的要求。對於第二點,不管是什麼雜湊演算法,只能儘量減少碰撞衝突的概率,理論上是沒辦法做到完全不衝突的。為什麼這麼說呢?

這裡就基於組合數學中乙個非常基礎的理論,鴿巢原理(也叫抽屜原理)。這個原理本身很簡單,它是說,如果有 10 個鴿巢,有 11 只鴿子,那肯定有 1 個鴿巢中的鴿子數量多於 1 個,換句話說就是,肯定有 2 只鴿子在 1 個鴿巢內。

那究竟為什麼雜湊演算法無法做到零衝突?

雜湊演算法產生的雜湊值的長度是固定且有限的。比如 md5 的例子,雜湊值是固定的 128 位二進位制串,能表示的資料是有限的,最多能表示 2128 個資料,而要雜湊的資料是無窮的。基於鴿巢原理,如果我們對 2^128+1 個資料求雜湊值,就必然會存在雜湊值相同的情況。一般情況下,雜湊值越長的雜湊演算法,雜湊衝突的概率越低。

不過,即便雜湊演算法存在雜湊衝突的情況,但是因為雜湊值的範圍很大,衝突的概率極低,所以相對來說還是很難破解的。像 md5,有 2128 個不同的雜湊值,這個資料已經是乙個天文數字了,所以雜湊衝突的概率要小於 1/2128。

如果拿到乙個 md5 雜湊值,希望通過毫無規律的窮舉的方法,找到跟這個 md5 值相同的另乙個資料,那耗費的時間應該是個天文數字。所以,即便雜湊演算法存在衝突,但是在有限的時間和資源下,雜湊演算法還是被很難破解的。

除此之外,沒有絕對安全的加密。越複雜、越難破解的加密演算法,需要的計算時間也越長。比如 sha-256 比 sha-1 要更複雜、更安全,相應的計算時間就會比較長。密碼學界也一直致力於找到一種快速並且很難被破解的雜湊演算法。我們在實際的開發過程中,也需要權衡破解難度和計算時間,來決定究竟使用哪種加密演算法。

應用二:唯一標識應用三:資料校驗應用四:雜湊函式

雜湊函式也是雜湊演算法的一種應用。

雜湊函式是設計乙個雜湊表的關鍵。它直接決定了雜湊衝突的概率和雜湊表的效能。不過,相對雜湊演算法的其他應用,雜湊函式對於雜湊演算法衝突的要求要低很多。即便出現個別雜湊衝突,只要不是過於嚴重,都可以通過開放定址法或者鍊錶法解決。

不僅如此,雜湊函式對於雜湊演算法計算得到的值,是否能反向解密也並不關心。雜湊函式中用到的雜湊演算法,更加關注雜湊後的值是否能平均分布,也就是,一組資料是否能均勻地雜湊在各個槽中。除此之外,雜湊函式執行的快慢,也會影響雜湊表的效能,所以,雜湊函式用的雜湊演算法一般都比較簡單,比較追求效率。

應用五:負載均衡

負載均衡演算法有很多,比如輪詢、隨機、加權輪詢等。那如何才能實現乙個會話粘滯(session sticky)的負載均衡演算法呢?也就是說,需要在同乙個客戶端上,在一次會話中的所有請求都路由到同乙個伺服器上。

最直接的方法就是,維護一張對映關係表,這張表的內容是客戶端 ip 位址或者會話 id 與伺服器編號的對映關係。客戶端發出的每次請求,都要先在對映表中查詢應該路由到的伺服器編號,然後再請求編號對應的伺服器。這種方法簡單直觀,但也有幾個弊端:

如果借助雜湊演算法,這些問題都可以非常完美地解決。可以通過雜湊演算法,對客戶端 ip 位址或者會話 id 計算雜湊值,將取得的雜湊值與伺服器列表的大小進行取模運算,最終得到的值就是應該被路由到的伺服器編號。 這樣,就可以把同乙個 ip 過來的所有請求,都路由到同乙個後端伺服器上。

應用六:資料分片

雜湊演算法還可以用於資料的分片。舉兩例:

如何快速判斷是否在相簿中?

前面介紹了一種方法,即給每個取唯一標識,然後構建雜湊表。

假設現在相簿中有 1 億張,很顯然,在單台機器上構建雜湊表是行不通的。因為單台機器的記憶體有限,而 1 億張構建雜湊表顯然遠遠超過了單台機器的記憶體上限。

同樣可以對資料進行分片,然後採用多機處理。準備 n 臺機器,讓每台機器只維護某一部分對應的雜湊表。每次從相簿中讀取乙個,計算唯一標識,然後與機器個數 n 求餘取模,得到的值就對應要分配的機器編號,然後將這個的唯一標識和路徑發往對應的機器構建雜湊表。

當要判斷乙個是否在相簿中的時候,通過同樣的雜湊演算法,計算這個的唯一標識,然後與機器個數 n 求餘取模。假設得到的值是 k,那就去編號 k 的機器構建的雜湊表中查詢。

應用七:分布式儲存

現在網際網路面對的都是海量的資料、海量的使用者。為了提高資料的讀取、寫入能力,一般都採用分布式的方式來儲存資料,比如分布式快取。有海量的資料需要快取,所以乙個快取機器肯定是不夠的。於是,就需要將資料分布在多台機器上。

該如何決定將哪個資料放到哪個機器上呢?可以借用前面資料分片的思想,即通過雜湊演算法對資料取雜湊值,然後對機器個數取模,這個最終值就是應該儲存的快取機器編號。

但是,如果資料增多,原來的 10 個機器已經無法承受了,就需要擴容了,比如擴到 11 個機器,這時候麻煩就來了。因為,這裡並不是簡單地加個機器就可以了。

原來的資料是通過與 10 來取模的。比如 13 這個資料,儲存在編號為 3 這台機器上。但是新加了一台機器中,我們對資料按照 11 取模,原來 13 這個資料就被分配到 2 號這台機器上了。

因此,所有的資料都要重新計算雜湊值,然後重新搬移到正確的機器上。這樣就相當於,快取中的資料一下子就都失效了。所有的資料請求都會穿透快取,直接去請求資料庫。這樣就可能發生雪崩效應,壓垮資料庫。

所以,我們需要一種方法,使得在新加入乙個機器後,並不需要做大量的資料搬移。一致性雜湊演算法

假設有 k 個機器,資料的雜湊值的範圍是 [0, max]。將整個範圍劃分成 m 個小區間(m 遠大於 k),每個機器負責 m/k 個小區間。當有新機器加入的時候,我們就將某幾個小區間的資料,從原來的機器中搬移到新的機器中。這樣,既不用全部重新雜湊、搬移資料,也保持了各個機器上資料數量的均衡。

一致性雜湊演算法的基本思想就是這麼簡單。除此之外,它還會借助乙個虛擬的環和虛擬結點,更加優美地實現出來。

資料結構學習筆記七(雜湊演算法)

一 什麼是雜湊演算法 將任意長度的任意二進位制值串對映為固定長度的二進位制值串,這個對映的規則就是雜湊演算法,而通過原始資料對映之後得到的二進位制值串就是雜湊值。雜湊演算法需要滿足的要求 二 雜湊演算法的應用 雜湊演算法的應用非常廣泛,主要有安全加密 唯一標識 資料校驗 雜湊函式 負載均衡 資料分片...

資料結構學習筆記 雜湊表

1.什麼是雜湊表 1 雜湊表是從乙個集合a到另乙個集合b的對映。2 集合a中的元素稱為鍵值,集合b中的元素稱為hash值。3 對映在數學上相當於乙個函式,集合a中的元素如何對映到集合b,hash函式決定。4 若兩個不同的鍵值對應同乙個hash值,這種情況為hash碰撞。2.雜湊與查詢 設集合a為查詢...

資料結構學習筆記 2 資料結構與演算法

四.演算法設計的要求 五.演算法效率的度量方法 六.函式的漸近增長 七.演算法時間複雜度 八.常見的時間複雜度 九.最壞情況與平均情況 十.演算法空間複雜度 資料結構是底層,演算法高層。資料結構為演算法提供服務。演算法圍繞資料結構操作。演算法是解決特定問題求解步驟的描述,在計算機中表現為指令的有限序...