IPFS的存儲與讀取

IPFS簡介

本篇文章主要想通過純理論的方式分析IPFS的原理,儘量不使用命令和代碼。關於IPFS的誕生以及取代HTTP的可能性分析,已經有太多大神寫過文章了,這裡就不再贅述了。感興趣的前往這裡瞭解 http://ipfser.org、以及IPFS白皮書。

一、 什麼是IPFS

IPFS, 星際文件系統 ( InterPlanetary File System )。2014年開始由Protocol Labs (協議實驗室)在開源社區的幫助下發展。其最初由Juan Benet設計。是一個旨在創建持久且分佈式存儲和共享文件的網絡傳輸協議。是永久的、去中心化保存和共享文件的方法,這是一種內容可尋址、版本化、點對點超媒體的分佈式協議。

內容可尋址:通過文件內容生成唯一哈希值來標識文件,而不是通過文件保存位置來標識。相同內容的文件在系統中只會存在一份,節約存儲空間版本化:可追溯文件修改歷史點對點超媒體:P2P 保存各種各樣類型的數據可以把 IPFS 想象成所有文件數據是在同一個 BitTorrent 群並且通過同一個 Git 倉庫存取。

二、 IPFS的存儲與讀取

接下來先基礎地介紹下IPFS是怎麼進行存儲和讀取的。IPFS文件的存儲和讀取與BitTorrent上傳下載原理相似。IPFS採用的索引結構是DHT(分佈式哈希表),數據結構是Merkle DAG(Merkle 有向無環圖)。

2.1 單文件存儲

研究過文件系統的人都知道索引和扇區這兩個概念,如:NTFS一個扇區通常是4K,真正的文件數據都是保存在扇區裡面的,找到這些扇區的方式就是建立索引(確切的說是高效的索引),IPFS也是一個文件系統,不同的是,IPFS是沒有存儲上限的,且不存在空間回收的功能。IPFS存儲文件時,如圖(沒天賦,略醜),會經歷以下幾個步驟:

1. 把單個文件拆分成若干個256KB大小的塊( block,這個就可以理解成扇區 );

IPFS的存儲與讀取

2. 逐塊(block)計算block hash,hashn = hash ( blockn );

3. 把所有的block hash拼湊成一個數組,再計算一次hash,便得到了文件最終的hash,hash ( file ) = hash ( hash1……n ),並將這個 hash(file) 和block hash數組“捆綁”起來,組成一個對象,把這個對象當做一個索引結構;

4. 把block、索引結構全部上傳給IPFS節點(這裡先不介紹細節),文件便同步到了IPFS網絡了;

5. 把 Hash(file)打印出來,讀的時候用;PS: 這裡可以看出IPFS計算文件得到的hash,其實和我們平時計算hash的方式不一樣,而且最終的結果也不一樣!

這裡還漏掉了一個小文件的處理邏輯,和NTFS等文件系統類似,小文件(小於 1KB) 的文件,IPFS會把數據內容直接和Hash(索引)放在一起上傳給IPFS節點,不會再額外的佔用一個block的大小。現在,已經把文件的原始數據和文件的索引(即hash)上傳到IPFS網絡了。前面已經講過,IPFS是不支持空間回收的,文件一旦同步到IPFS,將永久的存在。看起來這樣會招來一個嚴重的後果就是,如果頻繁的編輯大文件,每編輯一次就要重新同步,豈不是會過度浪費空間!?

舉個例子:本地有一個1G的大文件File1,已經同步到IPFS了,後面在這個文件File1後面追加了1K的內容,現在需要重新同步這個文件,算下來需要花費的空間應該是:1G+1G+1K;然而,事實並非如此。IPFS在儲存數據的時候,同一份數據只存儲一次,文件是分塊(block)存儲的,hash相同的block,只會存儲一次,也就說,前面1G的內容沒有發生改變,其實IPFS並不會為這些數據分配新的空間,只會為最後1K的數據分配一個新的block,再重新上傳hash,實際佔用的空間是: 1G + 1K ;

不同的文件有很多數據是存在重複的,如不同語言字幕的電影,影音部分相同的,只有字幕部分不一樣,當兩個不同國家的人都在上傳同一部電影的時候,這些文件在分塊(block)的時候,很有可能有大部分block的hash是一致的,這些block在IPFS上也只會存儲一份,這樣一來就可能會有很多文件的索引指向同一個block,這裡就構成了前面提到的一個數據結構——Merkle DAG(Merkle 有向無環圖)。下面盜個圖,形象的說明下DAG是個什麼東東。

IPFS的存儲與讀取

因為所有的索引上都保存了hash,所以Merkle DAG具有以下特點(從白皮書上扒下來的):1. 內容可尋址:所有內容都是被多重hash校驗和來唯一識別的,包括links。2. 無法篡改:所有的內容都用它的校驗和來驗證。如果數據被篡改或損壞,IPFS會檢測到。3. 重複數據刪除:重複內容並只存儲一次。

2.2 文件樹存儲

IPFS支持目錄結構,存儲目錄的方式很簡單:

1. 先把目錄下所有的文件同步到IPFS網絡中去,為所有的文件hash建立一個別名,這個別名其實就是本地文件名,把hash和別名“捆綁”在一起組建成一個名為 IPFSLink 的對象;

2. 把該目錄下所有的 IPFSLink 對象組成一個數組,對該數組計算一個目錄hash,並將數組和目錄hash拼成一個結構體,同步到IPFS網絡;

3. 如果上層還有目錄結構,則為目錄hash建立一個別名(就是目錄名),把目錄hash和別名“捆綁”在一起組建成一個 IPFSLink 的對象,重複從步驟2開始執行;

4. 把目錄hash打印出來,讀取的時候用;

由上可以看出,對於IPFS而言,存儲目錄和文件其實是一樣的處理方式,IPFS甚至根本沒有關心節點想要存儲的是一個目錄還是一個文件。

2.3 單文件讀取

IPFS取文件的方式,就比較簡單了,就是存儲方式的一個逆推過程:

1. 根據hash搜索該hash的索引結構,即找到該文件hash 的 block hash數組(這一步由IPFS網絡完成,是曠工該乾的事情),下載下來;

2. 此時已經得到了 block 的索引,根據block hash,搜索block所在的節點位置,下載下來;

3. 本地拼裝block:根據block hash數組的順序,把文件拼湊好。

block的下載是IPFS的核心,這中間涉及到很多複雜的技術細節,因為個人能力有限,這裡沒有展開討論,只是先一筆帶過。希望不會誤導新入門的讀者,以為IPFS就只幹了這麼點事情!

2.4 文件樹讀取

目錄的讀取也是目錄存儲過程的逆推:

1. 根據hash搜索該hash的索引結構,找到該目錄的 IPFSLink 對象數組,即目錄下的子列表;

2. 遍歷數組,如果IPFSLink對象是文件,則取出文件的hash下載該文件;

3. 如果IPFSLink對象是目錄,取出目錄hash,重新從步驟1開始執行;

三、 IPFS的未來

總的來說,IPFS具備很多良好的特性,如:自帶高可用屬性,不會宕機(除非全球停電或者斷網)、抗DOS、防篡改……不需要購買昂貴的防火牆設備來做這些事情。其他的優點請自行去 ipfser.org get!

此文對你有幫助請點點關注!


分享到:


相關文章: