1. 程式人生 > >【大話存儲II】學習筆記(18章),數據前處理和後處理

【大話存儲II】學習筆記(18章),數據前處理和後處理

分享圖片 精簡 upload 還需 客戶 相同 簡單 觸發 不同

存儲其實就是一臺主機,上面也運行著各種各樣的應用程序,可以在原本的裸數據之上實現更高級的功能,實現更多的附加值。現在的高端存儲越來越開發,比如EMC 的 V-MAX,高端存儲也用普通的x86了。

存儲系統有兩大功能:數據存儲和數據管理。

  • 數據存儲:控制器、磁盤、HBA卡等,主要是提供裸數據存儲服務。

  • 數據管理:分層、快照、克隆等高級功能。又可把數據管理部分分為對數據的前處理和後處理

    • 前處理:數據未放入磁盤之前的初加工,或者對存放空間做預先準備,比如精簡、重刪

    • 後處理:數據寫入磁盤之後,再將數據讀出來進行處理。比如數據遷移。

    有些功能既有前處理的過程,又有後處理的過程。比如快照,快照的生成是後處理,但是生產後,每個IO會Copy on Write,這就是典型的前處理。

    所以存儲除了比主機多運行了一些更強大更復雜的功能之外,其他與主機無異,比如快照、重刪、鏡像、復制等。

Thin Provision

超供的模式

精簡也即Thin Provision,但是精簡這種翻譯故弄玄虛,不如叫超供(Over Allocation)最能反映本質。

我們知道申請一個3G的網絡硬盤,供應商不會真的提供3GB的空間,它只是記錄一下,只有真的塞入了3GB的數據,才會占用這麽多空間。

這是怎麽辦到的?因為不是每個人都會把自己的空間用完,如果前面先把空間分配出去了,又一直沒有人占用,空間上就有浪費。這樣系統其實可以在後臺悄悄的把空間分配給其他的客戶端,相當於對客戶端進行欺騙

這種方法其實非常常見,比如說在銀行存錢10000塊,銀行不會一直給你保留那麽多錢,而是會把錢偷偷的拿來放貸。這是因為不是每個人都會立刻取錢的,完全可以拆東墻補西墻。

總結一下,所謂超供,就是指分配給你的空間是虛的,只有在實際用到的時候才占用空間。所以存儲系統需要實時監控物理空間的使用情況,一旦到了臨界值,則需要擴容。

要實現超供,NAS系統較容易實現,因為NAS系統是自己維護文件與物理空間的對應關系的。但是如果存儲系統提供的是,因為文件與物理空間的映射其實是由更上層的文件系統維護的,存儲系統本身是感知不到的。

那麽Thin Provision是怎麽實現的呢?

  • 如果存儲系統使用文件系統的思想:

    文件系統中有一種稀疏文件,Sparse File,它的作用是在向文件中寫入大量的0的時候,實際上只在內存上生成這些0,只是在真正需要的時候才分配空間。

    所以只需要對Spare File進行修改,然後把LUN設置為一個Sparse File就可以了。

  • 如果存儲系統不是使用文件系統的思想

    我們自然需要單獨維護一張邏輯地址與物理地址的映射表,可以以連續條帶做為單位來進行擴充。

    問題就是隨著時間的推移,有可能會出現邏輯上連續的條帶但是在物理上卻不連續的情況,所以大塊連續的IO卻變成了隨機IO,效率自然低下。

Thin Provision對性能的影響

Thin Provision對性能的影響主要在:耗費額外的CPU周期、物理空間碎片上。

  • 額外的CPU周期:

    收到一個讀IO,需要查Bitmap看讀IO的目的地址是否已經分配了空間,如果沒分配,則需要返回應全0x00,同樣對寫IO,則需要查目的地址是否被寫過,如果被寫過的話,還需要查找其他的空間。多了很多的步驟,而且還需要維護元數據,對計算資源消耗比較大。

  • 物理空間碎片:

    因為Thin是隨用隨分配,如同操作系統對內存的管理一樣,則一定會產生碎片的,不樣連續的空間可能被多個LUN占用,活生生的把連續IO變成了隨機IO,效率自然降低。

要實現Thin的核心模塊,只要有三大元數據就夠了:位圖、表、樹。

  • 位圖:記錄底層連續物理空間那些分配了,哪些未被分配。

  • 表:記錄LUN邏輯地址與物理地址的對應關系。因為邏輯地址已經不於傳統的物理地址一一對應了。這張表需要按照邏輯地址進行排序,以便於查詢。

  • 樹:在內存中生成,用於迅速的查詢表的結構。

比如使用64b的地址長度, 分配粒度32KB,也就是說每32KB的物理塊就用一個64b的地址進行表示。因為表代表了邏輯與物理地址的對應關系,所以表的每一項條目大小就是128b。對於100TB來說,對應的表的容量為$(100TB/32KB)*128b=512MB$,如果使用1MB的塊粒度,則元數據降為16MB/TB,差別還是很大的。

而且元數據這麽大,不可能全部放到內存裏面,所以又會牽扯到讀寫磁盤,性能嚴重下降。

Thin Provision脆弱性

  • 對性能影響太大:

    有些廠商的產品,開啟了Thin功能,性能降了70%,而粒度與性能總是一對矛盾,為了性能而增加粒度,就會喪失Thin的意義。

    Thin還會引入碎片的問題,所以需要進行碎片整理,與文件系統的碎片整理不同,LUN碎片整理指的是把分配到不同的RAID組上的碎片進行整理,而文件系統碎片整理指的是對LUN內的邏輯上文件碎片進行整理。

  • 效果很難維持:比如說在文件系統再進行了碎片整理,它會讀出零散的碎片,合並以後寫到新的位置,對Thin LUN來說,又需要重新分配新位置。比如100GB的LUN上有50GB的碎片,現在Thin LUN可能只分配了70GB物理空間,進行文件系統碎片整理以後,讀出50GB的碎片,發現還需要30GB空間,這樣反而把之前沒有分配的30GB重新分配掉了。

    再比如有些應用程序會生成大量的臨時文件,結束以後就刪除了,但是實際上底層LUN無法感知到,而且已經分配出去了,就沒法回到原來了。

    綜上,Thin Provision其實很脆弱,真的要不反彈的瘦,需要從應用層業務層入手,杜絕垃圾的產生。
    技術分享圖片

LUN Space Reclaiming

比如存儲只有1TB的空間,多個客戶端的LUN分布在上面,現在只剩下了500GB,此時如果誰還需要500GB的LUN空間做某程序的TMP空間,則管理員只要把所有空間都給它。但是程序運行完畢以後,臨時文件已經刪除,但是因為這些空間之前已經分配了,所以無法再次利用。

若通過縮小LUN來解決這個問題,需要消耗太多的資源,那麽有其他的方法麽?

  • 存儲可以自動識別對應的文件系統,當然就知道那些空間可以回收了,但是實際上目前沒有產品進行嘗試,因為主機端的文件系統多種多樣,就算同一種系統,內核版本不同差別也蠻大的。而且,主機端文件系統是有緩存,如果存儲端擅自回收空間的話,可能造成數據不一致。

  • 存儲系統自動識別0x00然後刪除他們:

    文件系統在刪除文件的時候,只是把文件從元數據中抹掉,如果再加一步,將占用的Block寫入0x00的話,那麽存儲系統可以定期掃描LUN,發現大片連續的0x00,則回收空間。這種技術叫Zero Detection。缺點是,每次刪除文件的時候,都需要寫入大量的0進行戰場的清掃,耗費的資源是極不劃算的。

    不過這種方法在特定的場景比較有用,比如VMware在新建虛擬機的時候,需要大量寫0,先把空間占住,這樣做的目的是看看存儲系統能提供的空間是否夠用。所以可以使用這種Zero Detection把連續的0x00的空間回收掉。再比如Oracle數據庫也有大片大片的0x00,通過這種方式也可以節省空間。

  • 主機端通過API通知存儲系統。

    在主機端運行一個代理程序,定期掃描剩余空間並將對應信息返回存儲控制器。類似與SSD的Trim技術,幾乎所有的SSD廠商都有空間回收專用程序。

技術分享圖片

分級

分層存儲管理的意義

技術分享圖片

我們知道對存儲介質而言,性能與價格是不可兼得的。上圖就表現得很明顯,對於Cache ,RAM速度快,但是價格高,而且是易失的,也就是一掉電啥就沒有了。

存儲介質到了磁盤這一層,又到了個質變點,磁盤之下的虛擬磁帶庫、磁帶都是不可隨機訪問的,只能當做離線存儲來用。而虛擬磁帶庫之所以稱為近線存儲,是因為從在線存儲將數據遷移到離線存儲之後,一旦短時間內需要再次訪問,需要忍受非常低的速度,而虛擬磁帶庫可以把數據快速提取出來,雖然仍然不可以隨機存取而已。

所以數據分級意義在於,將訪問頻繁、性能要求高的數據放在性能高的磁盤或者RAID組裏面,不經常訪問的數據移到低端硬盤裏面去。這樣就可以物盡其用。

技術分享圖片

數據分級的具體形式

  • 手動、自動、實時自動分級

    顧名思義,手動分級需要用戶自行遷移數據,而自動分級很大程度代理了用戶本身,只需要提前設置規則,由分級引擎掃描元數據,一旦符合條件,則觸發遷移任務。

    實時自動分級指的是數據寫入的時候,分級引擎實時將數據重定向到對應目標。

  • 文件級分級和塊級分級

    文件級分級可以做到更細化策略,比如可以根據擴展名、訪問頻率等屬性來進行分類。而且數據遷移到其他的Tier以後,原始的Tier上需要保持一個指針,目的是不影響用戶的使用,因為用戶程序是不會感知道文件實體放在哪裏,它只需要知道文件的路徑就可以了。

    基於塊級別的數據分級所能使用的觸發條件就少很多了,比如根據整個LUN或者某些Block的訪問頻度來進行遷移,因為塊級別無法感知道上層文件邏輯。

  • 主機端分級和存儲端分級

    主機可以同時連接到多個外部存儲上,所以如果在主機上分級可以實現數據在不同的外部存儲上遷移。一般來說,需要在主機端上安裝代理軟件來監視和管理。

    存儲系統的數據分級只能將數據在自身不同的Tier上遷移, 是完全對主機端透明的。

  • 應用級分級和底層級分級

    針對於應用系統,比如數據庫軟件催生了專門的數據管理工具,比如對數據進行容災、分級遷移。

    運行在主機端的數據分級管理程序則以普適為原則,針對任何文件、LUN進行遷移。

技術分享圖片

怎麽判斷熱點數據

一般利用二八原則,把數據按照單位時間內被IO次數來進行排序,訪問次數最多的20%數據為熱數據

塊級自動分級的底層數據結構

自動分級存儲一般需要追蹤每個塊的屬性,比如最後訪問時間、某段時間內訪問了多少次等數據。保存的這些數據有兩種方法:

  • 每個塊裏的首或者尾追加部分空間來存放這些元數據,這就是帶內元數據法

  • 單獨構建一個小型數據庫來存放所有塊的元數據,這個數據庫的數據存放在一個單獨的空間,這就是帶外元數據法

    對於帶內元數據法,系統即使是讀,也會更新元數據塊,而且分布在磁盤各處,性能問題嚴重。一個解決方法是使用日誌,將要更新的東西記錄在日誌裏面,在不繁忙的時候進行重放,這種方法註定要頻繁的IO操作,極其浪費資源。

    帶外元數據法更符合常理,不需要對數據塊做任何結構改變,可以使用獨立的軟件模式來交付。

集群、分布式文件系統天生就是自動分級的坯子,因為本來一個文件或者一個LUN的不同部分就可以放到不同的位置上,只需要在上面進行一些開發就可以很容易的實現分級。

對性能的影響

與 Thin Provision一樣,分塊粒度越小,性能損失越大。

  • 分塊越小,元數據量大量增加,搜索和處理效率降低。

  • 而且分級之後的數據塊在物理上不連續了,增加了尋道操作,降低了性能。

技術分享圖片

Deduplication(重刪)

不同機器的本地存儲裏面有若幹文件,如果這些文件存在重復,每次備份自然有很多的相同部分,比較浪費空間,有沒有辦法來解決:

在開始講解決方法之前,我們可以先總結一下出現重復可能的場景:

  • 同一主機或者不同主機的本地存儲的重復文件

  • 不同主機在同一NAS或者同一塊存儲上的重復文件

  • 虛擬機磁盤鏡像文件的重復部分

  • 虛擬機下裸磁盤映射模式的重復部分
    技術分享圖片

    SIS的缺陷

    傳統的解決方案是Single Instance Storage(SIS,單一實例存儲),可以相同內容的文件在系統中只存在一份實體,其他副本只作為指針鏈接而存在。註意這種技術只能避免相同內容的文件,所以只能解決同一主機裏的重復文件以及連接多主機的NAS設備上的重復文件。

但是對於多臺主機連接到同一塊存儲這種場景,因為塊存儲對每一臺主機提供不同的LUN,所以就類似於不同主機的本地存儲有重復文件一樣,所以依然是無能為力的。

我們知道虛擬機的鏡像其實就是一堆文件而已,但是這些文件不大可能在每個字節上都相同,即使是安裝的同一種操作系統,但是安裝的應用當然是不同的。所以SIS對這種場景也無能為力。

最後一種情況,根本看不到文件,當然也不能實現重刪。

SIS可以理解為文件級別的重刪,不能解決所有場景的問題。而且在底層實現上也有極大的局限性,比如只能以整個文件作為對比,對於那種大部分相同但是有細微差別的文件就沒辦法處理了。

所以塊級別的重刪才是有意義的。可以直接比對Block的內容,消除多個副本,在元數據中只留一個指針來指向唯一一份實體即可。

dedup與壓縮有什麽區別?壓縮只是局部上進行處理,而Dedup可以實現全局數據的重刪。

技術分享圖片

核心技術——HASH

重刪用到的關鍵技術就是HASH算法。在數據庫(三),底層算法中我們已經說了Hash算法之神奇。下面再簡單的介紹一下它的應用場景。

我們知道每個人的指紋各不相同,於是可以通過比對指紋就可以確定是否是同一個人留下的。同理,如果給每個Block錄一個指紋,就可以快速比對出這兩個塊是否是完全一樣呢。

那麽生成數據指紋的有一種很好的算法,就是HASH。它又衍生出MD5(Message Digest v5)和SHA-1(Secure Hash Algorithm v1)。

這些算法的特點在於

  • 不管數據有多長,只要不超過額定大小,經過計算以後,一定可以得到一個固定長度值,比如SHA-1對一段小於264的數據進行計算以後,可以得到一個長度為160的值。

  • 同時相同的數據經過HASH以後,總會得到相同的指紋

  • 而且這種HASH方法是不可逆的,也就是說通過指紋不能算出原來的值是多少。

HASH算法有很多的應用。

  • 應用一:因為HASH以後的值不能被逆算出,所以我們完全可以將其用於登錄密碼保存上,這樣即使黑客將密碼HASH以後的值攔截到了,依然無法逆算出原來的密碼。

    那麽你可能要問,用戶正常登錄的時候如何匹配呢?這個時候,只要我們在後端的數據庫裏面依然存放密碼的HASH以後的值即可,只要密碼HASH以後的值與數據庫中存放的對應內容匹配,則認證成功。

  • 應用二:還有就是聽歌識曲的功能,比如錄制的一段曲子傳到服務器上,服務器就可以告訴你這段曲子的名稱。實際也就是根據曲子的音調生成指紋,然後於數據庫大量的標本進行匹配,發現類似的歌曲返回名稱即可。

  • 應用三:判斷數據傳輸的時候是否在內容上發生了改變。只要在源端算一個指紋,目的端再算一次,對比兩個指紋是否一致即可知道是否改變。

  • 應用四:遠端Cache。某個CDN內容發布在網絡環境中,針對一份源數據,在各地擁有多個二級Cache。這些Cache需要嚴格保證一致性,如果源發生了改變,指紋當然也改變了。那麽可以隨時拉取源端的指紋進行對比,發現不匹配則此Cache不再可用。

  • 應用五:數字簽名。將某人給出的一串特定字符轉換成指紋。

技術分享圖片

HASH沖突

要完全杜絕Hash沖突的唯一辦法就是當對比兩個HASH值的之後發現二者匹配以後,可以再進行逐位對比,或者取相同的部分進行對比。

但是這樣做的話會耗費大量的計算和IO資源,我們可以換一種思路,取兩種HASH算法進行計算,如果兩次都比對都相同,則可以認為是重復的。

主機Dedup的過程

Dedup主要包含如下4個動作,註意這裏面的Dedup軟件是安裝在主機上的。
技術分享圖片

  • 主機的Filter Driver實時監測寫IO,透傳到下層,同時復制一份到Dedup主模塊。

    Dedup主模塊將寫IO Hash以後,存到指紋倉庫裏面,對Delay Block Bitmap置0。這個Bitmap是幹嘛的?如果因為CPU負載過高等原因,Dedup引擎暫停工作,則這個寫IO會被計算成Hash值存放,我們可以用一個bitmap來記錄這寫IO的位置,後續再進行計算。

  • Dedup主模塊會在後臺查找與指紋庫裏面重合的指紋,對於查找的菜塊,會生成一個指針,並且保存在On Disk Pointer List中。這個動作是有Block Mapping Metadata Handler完成的,這個過程是真正的數據消重的過程。

  • 針對Bitmap裏面記錄的暫未計算HASH的部分,還會在空閑的時刻完成後續的操作,並且把Bitmap的對應位置置回0

這裏面需要註意的是每個寫IO都會寫入存儲介質中。那麽大家肯定有疑問了,既然每個寫IO都落到磁盤上,何來消重。

其實這個問題之前已經討論了很多次了。誰來決定LUN的剩余空間,當然是上層文件。所以如果我們要想讓主機端的Dedup有意義,只能

  • 讓主機端文件系統感知到變化:這對塊級Dedup來說是行不通的,因為塊級Dedup的實現原理沒有考慮到FS層的邏輯

  • 模仿主機端對LUN的管理:可以在LUN上建立一層卷管理層,這樣卷管理層會感知到哪些卷占用了多少物理空間。

雖然運行在主機端、塊級的Dedup,無法達到節省底層存儲空間的目的。但是在備份的時候就非常有意義了,因為可以減少網絡傳輸的量。

其實根本不用這麽糾結,我們完全可以把塊級Dedup安裝在存儲端,因為我們最終要節省的就是磁盤空間,而磁盤又是由存儲設備管理的
技術分享圖片

網絡數據備份的Dedup

上面說過主機上的Dedup對備份是有意義的,我們可以傳輸更少的數據。不過這要求Dedup引擎與備份系統緊密配合,一般來說是作為備份軟件的一個子模塊

這樣做有個不好的地方,也就是會消耗主機的性能。我們也可以在主機後面進行Dedup,比如在介質服務器上,可以使用前臺Dedup或者後臺Dedup

  • 如果備份介質是磁帶,則必須以前臺的方式來進行,因為磁帶不可隨機訪問。

    前臺Dedup可以采用局部和全局兩種模式。區別在於對收到的數據是否還需要與之前備份過的數據進行對比。

    • 局部模式:Dedup引擎對收到的數據實時分割為Block然後計算HASH,並存放在指紋倉庫裏面。

    • 全局模式:對接收來的數據計算HASH值以後,會將這個HASH值與之前曾備份過的數據的HASH值進行對比。

    介質服務器都有本地硬盤,可以將要備份的數據流暫存在本次硬盤某處作為緩沖,然後由Dedup引擎在後臺處理,最後寫入磁帶,這就是D2D2T

  • 後臺Dedup:如果備份介質是虛擬磁帶庫VTL,則可以使用這種方法。

    介質服務器首先將收的數據流直接寫到磁盤中,當引擎觸發之後,再從對應目標將數據讀出並進行Dedup處理,最後寫入介質空間,原有備份數據集刪除。
    技術分享圖片

Dedup思想的其他應用

增量備份、差量備份通常是在應用程序層來控制的,因為主要是由應用程序來負責記錄備份的時間點以及文件的變化,此時備份軟件主要是輔助作用。

然而備份軟件自身如何實現LUN級別的增量和差量備份呢?

  • 差量備份:記錄底層Block變化,將上一次備份之後,所發生的所有寫對應的Block記錄在bitmap中。這樣就知道那些是需要再備份的。

  • 增量備份:可以將上一層的Bitmap封存,新建一份空的Bitmap保存上一次差量或增量備份LUN的變化。當再次觸發備份的時候,將Bitmap中置1的塊備份下來,然後封存Bitmap,創建新的Bitmap。恢復的時候,可以根據需要恢復的備份點,將所有的Bitmap做一個OR操作,合成一份完整的Bitmap。然後將初次全備份的數據覆蓋到目標上。這樣就可以根據完整的Bitmap和每次增量備份的Block集提取對應的Block進行備份。

【大話存儲II】學習筆記(18章),數據前處理和後處理