Distributed Hash Tables(DHT)
分布式哈希表是一個分布式的鍵值對存儲結構。在IPFS網絡中,每一個節點都維護一個DHT的子集。當節點接受到一個請求。該節點要么直接回復,要么通過節點間傳輸直到找到可以回復該請求的節點。取決於實現方式,一個請求如果不能被第一個連接的節點回復
- 進行節點間的轉發,由最后一個節點聯系收到請求的節點。
- 進行節點間的轉發,回復結果按照相同的路徑轉發回到原節點。
- 由最優選擇的節點對請求進行回復。
IPFS使用這種策略。
DHT的去中心化提供了相比於傳統的鍵值對存儲更好的優勢。包括:
- 擴展性。對長度為n的哈希請求只需要最多為log2n步即可解決。
- 通過冗余進行錯誤容忍。即可能每一個節點都加入或離開DHT。另外,如果一個節點反應緩慢或者不可達,請求可以連接到其他節點。
- 負載均衡,請求可以發送到任何節點,沒有任何一個節點處理所有的請求。
DHT如何工作
Peer IDs
每一個節點有有一個peerID
,和DHT的鍵相同都是長度為n的哈希值。
Buckets
由每一個節點維護的DHT的子集被稱為”桶“,一個桶映射的哈希值和節點ID具有相同的前綴。最多m個比特位。有2m個桶,每個桶則映射2n-m個哈希值。
例如,如果m=2^16,並且使用16進制數據,節點ID為ABCDEF12345
,維護以ABCD
為前綴的哈希值映射。桶內的哈希值則可能為*ABCD*38E56,*ABCD*09CBA,*ABCD*17ABB
.
節點列表
節點之間保持連接到其他節點為了轉發請求(當請求的哈希值不在當前節點的桶內)
如果哈希值長度為n,一個節點將保持連接n-1個列表節點。
- 第一個列表維護第一個比特值不同的節點ID的節點。
- 第二個列表維護前一個比特值相同,第二個比特值不同的節點ID的節點。
- 第三個列表維護前兩個比特值相同,第三個比特值不同的節點ID的節點。
- ...
假設最高的是第m個列表,很難發現最多有m個比特值相同的節點ID的節點。“最接近”對等方的列表通常保持空白。此處的“最接近”定義為XOR距離,因此它們共享的前綴越長,它們就越接近。列表還具有最大的條目(k)-否則第一個列表將包含一半的網絡,然后是網絡的四分之一,依此類推。
DHT使用
當節點接受到查詢請求后,如果可以在自己的桶中找到答案則回復。否則聯系最接近該節點的節點(IP+port,peerID,等等)回復。收到請求的節點尅將請求發送給最接近的節點。這個過程一直到可以回復請求的節點。一個哈希值長度為n的請求最多只需要log2n步,甚至是log2mn步。
鍵和哈希值
在IPFS的Kademili DHT,鍵使用SHA256哈希。節點ID使用由IPFS使用的網絡庫libp2p。
使用DHT查看兩種類型的對象時,都由SHA256進行散列:
- 添加到IPFS的數據的Content IDs。查找該值將給出具有該不變內容的對等方的peerID。
- IPNS記錄。查找將給出與此IPNS地址關聯的最后一個Content ID,從而啟用可變內容的路由。
所以,IPFS的DHT只是實現不可變與可變內容路由的一種方式.當前只是一種實現.
使用
添加一條記錄
添加一個blob
類型的數據到IPFS等同於廣播它,由於DHT由內容路由實現。可以通過ipfs add myData
自動打包數據挺添加內容ID和節點ID之間的映射到DHT。注意這里可能也被其他節點ID映射到該值,所以需要添加到列表中。如果提供的數據大於124KB,數據將會被打包成blocks
,整個塊將被映射。
可以通過使用ipfs.name.publish
發布一個IPNS記錄。