簡介
? ? SSD(Solid State Drives),俗稱固態硬盤,相對原來主軸旋轉,并無機械部分,主要由SSD控制器,Flash存儲陣列,板上DRAM(可選),以及與Host的接口(諸如SATA,SAS,PCIe等)組成。固態硬盤在接口的規范和定義、功能及使用方法上與普通硬盤的完全相同,在產品外形和尺寸上也完全與普通硬盤一致。
分類
? ? 根據存儲介質,SSD可分為DRAM型的SSD和Flash的SSD?;贒RAM的SSD,采用DRAM作為存儲介質,目前應用范圍較窄,它仿效傳統硬盤的設計、可被絕大部分操作系統的文件系統工具進行卷設置和管理,并提供工業標準的PCI和FC接口用于連接主機或者服務器。另外DRAM雖然速度更快但它屬于RAM類型是不能掉電的,一旦掉電RAM內的數據就都丟失了,所以DRAM基本不用來做SSD。
? ? 基于Flash的SSD,采用Flash芯片作為存儲介質,也是通常所說的SSD。這種SSD固態存儲器最大的優點就是可以移動,而且數據保護不受電源控制,能適應于各種環境,但是使用年限不高。
? ? Flash的SSD,根據電路區別,進而分為NOR(或非)型和NAND(與非)型。NOR的讀速度比NAND稍快一些,NAND的寫入速度比NOR快很多,NAND的4ms擦除速度遠比NOR的快。
? ? NAND又分為SLC、MLC、TLC。
? ? SLC全稱單層式儲存(Single Level Cell),是指一個Block(塊,Flash的基本存儲單元,也可稱為Cell)只有兩種電荷值,高低不同的電荷值表明0或者1,因為只需要一組高低電壓就可以區分出0或者1信號,所以SLC最大的驅動電壓可以做到很低,傳統的雙電壓卡或者低電壓版本卡片肯定采用SLC類型的NAND Flash芯片。SLC因為結構簡單,在寫入數據時電壓變化的區間小,所以壽命較長,傳統的SLC Flash可以經受10萬次的讀寫,因此出現壞Block的幾率較小,因為存儲結構非常簡單,一組電壓即可驅動,所以其速度表現更好,目前所有的超高速卡都采用SLC類型的Flash芯片。
? ? MLC(多層式儲存—Multi Leveled Cell)是種充分利用Block的技術,它采用較高的電壓驅動,通過不同級別的電壓在一個Block中記錄兩組位信息(00、01、11、10),這樣就可以將原本SLC的記錄密度理論提升一倍。不過MLC除了同制程、同晶圓面積時理論大一倍的記錄空間外,存在一些先天的弊端,比如說電壓區間更小,Flash就需要更多的CRC校驗空間,這會大概占據Block中10%的空間,因此實際使用中同制程同晶圓面積的MLC的容量不到SLC的一倍。
? ? 因為電壓變化更頻繁,所以MLC技術的Flash在壽命方面遠劣于SLC,官方給出的可擦寫次數僅為1萬次,這是MLC最要命的一個缺點。MLC技術的Flash還有一個缺點,它的讀寫速度先天不如SLC,一個Block存儲兩組位數據,自然需要更長的時間,這里面還有電壓控制、CRC寫入方式等因素需要考慮。
? ? TLC 三階存儲單元(Triple-LevelCell,TLC),每個存儲單元內可以存儲3個Bit。由于每個單元可以存儲更多的數據,TLC的成本進一步降低,但是隨之而來的是寫入速度和耐久度的再次降低。當然,現在市場上也有唯一一個采用TLC的SSD:三星的840,當然官方標注其P/E只有1K次。
基本原理
? ? SSD主控通過若干通道并行操作多塊Flash顆粒,類似Raid0,大大提高底層帶寬。
? ? 例:假設主控與Flash顆粒之間有8個通道,每個通道掛在了一個閃存顆粒,Host與Flash之間數據傳輸速率為200M/s,閃存顆粒大小為8kb,Flash page的讀取時間為Tr=50us,平均寫入時間為Tp=800us,8kb的數據傳輸時間為Tx=40us。
? ? 則,底層讀取最大帶寬為:(8KB/(50us+40us))*8 = 711MB/s;寫入最大帶寬為:(8KB/(800us+40us))*8 = 76MB/s;
? ? 從上可以看出,要提高底層帶寬,可以增加底層并行的顆粒數目,也可以選擇速度快的Flash顆粒。
? ? 以8通道為例,來講講HOST怎么讀寫SSD。主控通過8通道連接8個Flash DIE,為方便解釋,這里只畫了每個DIE里的一個Block,其中每個小方塊表示一個Page (假設大小為4KB)。
? ? HOST寫入4KB數據:
? ? HOST繼續寫入16KB數據:
? ? HOST繼續寫入,最后整個Block都寫滿:
? ? SSD內部尋址方式有別于HDD,下面先介紹一下尋址方式的區別。
? ? LBA,全稱為Logical Block Address, LBA,全稱為Logical Block Address,是PC數據存儲裝置上用來表示數據所在位置的通用機制,我們最常見到使用它的裝置就是硬盤。LBA可以指某個數據區塊的地址或者某個地址上所指向的數據區塊。打個比方來說,LBA就等于我們平常使用的門牌地址(如:中華人民共和國廣東省廣州市中山四路26號)。
? ? PBA全稱為 Physics Block Address PBA全稱為 Physics Block Address,相對于LBA來說,它就如GPS定位所使用的經緯度(如上面地址的經緯度為:東經:113°16′40.0621″,北緯:23°07′ 37.6129″)。
? ? 在HDD上,由于HDD的數據可以直接覆蓋,所以LBA和PBA的關系是一一對應,不會變更,即LBA=PBA。但在SSD上,這種關系就變得復雜了,原因是SSD使用的存儲介質NAND閃存需要先擦除才能再寫入,即讀寫以頁為單位,擦除以塊(多個頁組成)為單位的特性,導致LBA和 PBA的關系不再是固定不變的。因此SSD就需要一層叫做FTL(Flash translation layer)的東西來作轉換,以配合現有的文件系統。
? ? 閃存的讀寫單位為頁,而頁的大小一般為4KB或8KB,但我們的操作系統讀寫數據是按HDD的扇區尺寸進行的(512Byte),更麻煩的是閃存擦除以塊作單位,而且未擦除就無法寫入,這導致操作系統現在使用的文件系統根本無法管理SSD,需要更換更先進、復雜的文件去解決這個問題, 但這樣就會加重操作系統的負擔。而為了不加重操作系統的負擔,SSD采用軟件的方式把閃存的操作虛擬成磁盤的獨立扇區操作,這就是FTL。因FTL存在于文件系統和物理介質(閃存)之間,操作系統只需跟原來一樣操作LBA即可,而LBA到PBA的所有轉換工作,就全交由FTL負責.
? 回到之前的問題,當所有Channel上的Block都寫滿的時候,SSD主控會挑選下一個Block以同樣的方式繼續寫入.Host通過LBA訪問SSD,每個LBA代表著一個Sector(一般為512B大?。?,操作系統一般以4K為單位訪問SSD,我們把Host訪問SSD的基本單元叫用戶頁(Host Page)。而在SSD內部,SSD主控與Flash之間是Flash Page為基本單元訪問Flash的,我們稱Flash Page為物理頁(Physical Page)。Host每寫入一個Host Page, SSD主控會通過FTL找一個Physical Page把Host數據寫入,同時記錄了這樣一條映射(Map),并把這個頁上包含的“舊數據”標記為“無效”(更新后的數據已經寫入新的PBA,舊地址的數據自然就失效了)。有了這樣一個映射關系后,下次HOST需要讀某個Host Page 時,SSD就知道從Flash的哪個位置把數據讀取上來。
? ? SSD內部維護了一張映射表(Map Table),Host每寫入一個Host Page,就會產生一個新的映射關系,這個映射關系會加入(第一次寫)或者更改(覆蓋寫)Map Table;當讀取某個Host Page時, SSD首先查找Map Table中該Host Page對應的Physical Page,然后再訪問Flash讀取相應的Host數據。
? ? 一張Map Table有多大呢?這里假設我們有一個256GB的SSD,以4KB Host Page為例,那么一共有約 64M(256GB/4KB)個Host Page,也就意味著SSD需要有64M大小的Map Table。Map Table中的每個Entry存儲的就是物理地址(Physical Page Address),假設其為4Byte (32 bits) ,那么整個Map Table的大小為64M*4B = 256MB。
? ? 對絕大多數SSD,我們可以看到上面都有板載DRAM,其主要作用就是用來存儲這張映射表。也有例外,比如基于Sandforce主控的SSD,它并不支持板載DRAM,那么它的映射表存在哪里呢?SSD工作時,它的絕大部分映射是存儲在Flash里面,還有一部分存儲在片上RAM上。當Host需要讀取一筆數據時,對有板載DRAM的SSD來說,只要查找DRAM當中的映射表,獲取到物理地址后訪問FLASH從而得到HOST數據.這期間只需要訪問一次Flash;而對Sandforce的SSD來說,它首先看看該Host Page對應的映射關系是否在RAM內,如果在,那好辦,直接根據映射關系讀取Flash;如果該映射關系不在RAM內,那么它首先需要把映射關系從FLASH里面讀取出來,然后再根據這個映射關系讀取Host數據,這就意味著相比有DRAM的SSD,它需要讀取兩次FLASH才能把HOST數據讀取出來,底層有效帶寬減半。對HOST隨機讀來說,由于片上RAM有限,映射關系Cache命中(映射關系在片上RAM)的概率很小,所以對它來說,基本每次讀都需要訪問兩次Flash,所以我們可以看到基于Sandforce主控的SSD隨機讀取性能是不太理想的。
? ? 繼續回到之前的SSD寫操作。當整個SSD寫滿后,從用戶角度來看,如果想寫入新的數據,則必須刪除一些數據,然后騰出空間再寫。用戶在刪除和寫入數據的過程中,會導致一些Block里面的數據變無效或者變老。如下圖所示(綠色小方塊代表有效數據,紅色小方塊代表無效數據):
? ? Block中的數據變老或者無效,是指沒有任何映射關系指向它們,用戶不會訪問到這些FLASH空間,它們被新的映射關系所取代。比如有一個Host Page A,開始它存儲在FLASH空間的X,映射關系為A->X。后來,HOST重寫了該Host Page,由于FLASH不能覆蓋寫,SSD內部必須尋找一個沒有寫過的位置寫入新的數據,假設為Y,這個時候新的映射關系建立:A->Y,之前的映射關系解除,位置X上的數據變老失效,我們把這些數據叫垃圾數據。
? ? 隨著HOST的持續寫入,FLASH存儲空間慢慢變小,直到耗盡。如果不及時清除這些垃圾數據,HOST就無法寫入。SSD內部都有垃圾回收機制,它的基本原理是把幾個Block中的有效數據(非垃圾數據,上圖中的綠色小方塊表示的)集中搬到一個新的Block上面去,然后再把這幾個Block擦除掉,這樣就產生新的可用Block了。
? ? 上圖中,Block x上面有效數據為A,B,C,Block y上面有效數據為D,E,F,G,紅色方塊為無效數據。垃圾回收機制就是先找一個未寫過的可用Block z,然后把Block x和Block y的有效數據搬移到Block z上面去,這樣Block x和Block y上面就沒有任何有效數據,可以擦除變成兩個可用的Block。
? ? 垃圾回收又分為后臺GC和主動GC。
? ? 后臺垃圾收集算法(也稱為閑置垃圾收集),該控制器會使用空閑的時間來做垃圾收集,讓主控在使用時一直保持高性能。例如barefoot主控. 在空閑的時候進行GC.以提高SSD性能. 在空閑的時候進行GC.以提高SSD性能。
? ? 主動GC需要有相當性能的主控制器,以保證在操作數據的同時進行GC操作 在操作數據的同時進行GC操作,這類GC適合在服務器里用到,因為個人用戶可以把電腦閑置了做GC,但是服務器可不行,所以要保證性能的話必須在運行的同時做GC,這對主控制器的性能提出了很高的要求,SandForce與Marvell BJP2的主控就是這類。
? ? 一塊剛買的SSD,你會發現寫入速度很快,那是因為一開始總能找到可用的Block來進行寫入。但是,隨著你對SSD的使用,你會發現它會變慢。原因就在于SSD寫滿后,當你需要寫入新的數據,往往需要做上述的垃圾回收:把若干個Block上面的有效數據搬移到某個Block,然后擦掉原先的Block,然后再把你的Host數據寫入。這比最初單純的找個可用的Block來寫耗時多了,所以速度變慢也就可以理解了。
? ? 還是以上圖為例。假設HOST要寫入4KB數據 (H) ,由于當前可用Block過少,SSD開始做垃圾回收。從上圖可以看出,對Block x來說,它需要把Page A,B,C的數據讀出并寫入到Block z,然后Block x擦除用于HOST數據寫入。從Host角度,它只寫了4KB數據,但從SSD內部來說,它實際寫入了4個Page(Page A, B, C寫入Block z,4KB數據H寫入到Block x)。
寫入放大
? ? 2008年,Intel公司和SiliconSystems公司(2009 年被西部數字收購)第一次提出了寫入放大(Write Application)并在公開稿件里用到這個術語。
? ? 在上面例子中,Host寫了4KB數據,閃存寫了4個4KB數據,所以上面例子中寫放大為4。對空盤來說,寫放大一般為1,即Host寫入多少數據,寫入Flash也是多少數據量。在Sandforce控制器出來之前,寫放大最小值為1。但是由于Sandforce內部具有壓縮模塊,它能對Host寫入的數據進行實時壓縮,然后再把它們寫入到NAND。舉個例子,HOST寫入8KB數據,經壓縮后,數據變為4KB,如果這個時候還沒有垃圾回收,那么寫放大就只有0.5。Intel之前說寫放大不可能小于1,但Sandforce打破了這個說法。
預留空間
? ? 假設一個SSD,底下所有Flash容量為256GB,開放給用戶使用也是256GB,那么問題就來了。想象一個場景,Host持續寫滿整個SSD,接著刪除一些文件,寫入新的文件數據,試問新的數據能寫入嗎?在SSD底層,如果要寫入新的數據,必須要有可用的空閑Block,但由于之前256GB空間已經被HOST數據占用了,根本就沒有空閑Block來寫你的數據。不對,剛才不是刪了一些數據嗎?可以垃圾回收呀。不錯,但問題來了,在上面介紹垃圾回收的時候,我們需要有Block z來寫回收來的有效數據,我們這個時候連Block z都找不到,談什么垃圾回收?所以,最后是用戶寫失敗。
? ? 上面這個場景至少說明了一點,SSD內部需要預留空間,這部分空間HOST是看不到的。這部分預留空間,不僅僅用以做垃圾回收,事實上,SSD內部的一些系統數據,也需要預留空間來存儲,比如前面說到的映射表(Map Table),比如SSD固件,以及其它的一些SSD系統管理數據。
? ? 一般從HOST角度來看,1GB= 1,000,000,000Byte,從底層Flash角度,1GB=1*1024*1024*1024Byte。256GB FLASH 為256*2^30 Byte,而一般說的256GB SSD 容量為256*10^9 Byte,這樣,天然的有(256*2^30-256*^9)/(256*^9) = 7.37%的OP。
? ? 如果把256GB Flash容量的SSD配成240GB的,那么它的OP是多大呢?
? ? (256*2^30-240*10^9)/(240*10^9) = 14.5%
? ? 除了滿足基本的使用要求外,OP變大有什么壞處或者好處呢?壞處很顯然,用戶能使用的SSD容量變小。那么好處呢?
? ? 回到垃圾回收原理來。
? ? 再看一下這張圖。回收Block x,上面有3個有效Page,需要讀寫3個Page完成整個Block的回收;而回收Block y時,則需要讀寫4個有效Page。兩者相比,顯然回收Block x比回收Block y快一些。說明一個簡單的道理:一個Block上有效的數據越少(垃圾數據越多),則回收速度越快。
? ? 256GB FLASH配成256GB的SSD (OP = 7.37%), 意味著256*10^9的有效數據寫到 256*2^30的空間,每個Block上面的平均有效數據率可以認為是256*10^9/256*2^30 = 93.1%。
? ? 如果配成240GB的SSD,則意味著240*10^9的有效數據寫到256*2^30的空間,每個Block的平均有效數據率為240*10^9/256*2^30 = 87.3%。OP越大,每個Block平均有效數據率越小,因此我們可以得出的結論:OP越大,垃圾回收越快,寫放大越小。這就是OP大的好處。
? ? 寫放大越小,意味著寫入同樣多的Host數據,寫入到Flash中的數據越少,也就意味著Flash損耗越小。Flash都是有一定壽命的,它是用P/E數 (Program/Erase Count)來衡量的。如果SSD集中對某幾個Block進行擦寫,那么這幾個Block很快就壽命耗盡。比如在用戶空間,有些數據是頻繁需要更新的,那么這些數據所在Block就需要頻繁的進行擦寫,這些Block的壽命就可能很快的耗盡。相反,有些數據用戶是很少更新的,比如一些只讀文件,那么這些數據所在的Block擦寫的次數就很少。隨著用戶對SSD的使用,就會形成一些Block有很高的PE數,而有些Block的PE數卻很低的。這不是我們想看到的,我們希望所有Block的PE數都應該差不多,就是這些Block被均衡的使用。在SSD內部,有一種叫磨損平衡(Wear Leveling,WL)的機制來保證這點。
磨損平衡(Wear Leveling,WL)
? ? Wear leveling也是SSD內部的FTL實現的,它通過數據遷移來達到均衡損耗的目的。Wear leveling依賴于SSD中的一部分保留空間,基本原理是在SSD中設置了兩個block pool,一個是free block pool(空閑池),一個是數據池(data block pool),當需要改寫某個page時(如果寫入原有位置,必須先擦除整個block,然后才能寫入數據),并不寫入原有位置(不需要擦除的動作),而是從空閑池中取出新的block,將現有的數據和需要改寫的數據合并為新的block,一起寫入新的空白block,原有的block被標識為invalid狀態(等待被擦除回收),新的block則進入數據池。后臺任務會定時從data block中取出無效數據的block,擦除后回收到空閑池中。這樣做的好處在于,一是不會反復擦寫同一個block,二是寫入的速度會比較快(省略了擦除的動作)。
? ? WL有兩種算法:動態WL和靜態WL。所謂動態WL,就是在使用Block進行擦寫操作的時候,優先挑選PE 數低的;所謂靜態WL,就是把長期沒有修改的老數據(如前面提到的只讀文件數據)從PE數低的Block當中搬出來,然后找個PE 數高的Block進行存放,這樣,之前低PE數的Block就能拿出來使用。
? ? 下面這張圖詮釋了無WL,動態WL和靜態WL下的FLASH耐久度的區別 (假設每個Block最大PE數為10,000):(圖片來自http://www.pceva.com.cn/topic/crucialssd/images/6/006.jpg)
? ? 可見,使不使用WL,以及使用何種WL算法,對SSD的壽命影響是很大的。
SSD性能指標采集
? ? 既然SSD壽命是有限的, 監控磨損率等性能指標很有必要。收集SSD的信息前,首先要了解Raid信息。市場上比較常用的服務器,諸如DELL、Lenovo等,可用MegaCli查看Raid磁盤陣列信息。
? ? 查看Raid信息:MegaCli -AdpAllInfo -aALL
? ? 查看硬盤信息:MegaCli -PDList -aALL?
? ? 得到SSD的基礎信息后,可使用smartctl,進一步獲取SSD的詳細狀態參數。smartctr需要兩個參數,一個是device_id,已經在MegaCLI中獲取到,另一個參數是raid生成的設備,可在dmesg看到。有個這兩個參數后,就可以查看SSD的運行狀態了。
? ? 假設我們的device id是10,SSD在/dev/sda,那么可以用下面的命令查看具體信息:smartctl -a -d sat+megaraid,10 /dev/sda,結果如下圖。
? ? 輸出結果中,Media_Wearout_Indicator一項就是我們最關心的SSD的磨損率,另外還記錄了一些其他狀態參數,在這里不再贅述。
? ? 市面上的主流服務器中,HP是獨樹一幟的,MegaCli在這類品牌的機器上不好用。HP有自帶的工具hpssacli,記錄的信息比MegaCli要詳細一點,可以使用hpssacli ctrl slot=0 show config detail命令來查看slot 0的詳細信息。
? ? 輸出的結果中,Bay - 1就是我們上面使用的device id。之后,同樣的使用smartctl查看SSD的詳細信息:
? smartctl -a -d cciss, 0 /dev/sda
? ? 結果如下圖,其中Media_Wearout_Indicator就是我們想要的結果。
IO調度算法
? ? 傳統的IO調度算法中,大多數是針對于HDD的尋道時間進行優化,而SSD沒有尋道時間,所以對IO調度的算法有所側重。常見的IO調度算法中,最適合SSD是最簡單的NOOP。NOOP實現了最最簡單的FIFO隊列,所有IO請求大致按照先來后到的順序進行操作,在FIFO的基礎上還做了相鄰IO請求的合并。反觀CFQ、AS、DeadLine等算法,雖然各有所長,但論綜合能力來看,NOOP還是勝出的。