NOR和NAND
NOR和NAND都是快閃記憶體技術的一種,NOR是Intel公司開發的,它有點類似於記憶體,允許通過地址直接存取任何一個記憶體單元,缺點是:密度低容量小),寫入和擦除的速度很慢。NAND是東芝公司開發的,它密度高容量大),寫入和擦除的速度都很快,但是必須通過特定的IO介面經過地址轉換之後才可以訪問,有些類似於磁碟。
我們現在廣泛使用的隨身碟,SD卡,SSD都屬於NAND類型,廠商將flash memory封裝成為不同的介面,比如Intel的SSD就是採用了SATA的介面,訪問與普通SATA磁碟一樣,還有一些企業級的快閃記憶卡,比如FusionIO,則封裝為PCIe介面。
SLC和MLC
SLC是單極單元,MLC是多級單元,兩者的差異在於每單中繼存放區的資料量密度),SLC每單元只儲存一位,只包含0和1兩個電壓符,MLC每單元可以儲存兩位,包含四個電壓符00,01,10,11)。顯然,MLC的儲存容量比SLC大,但是SLC更簡單可靠,SLC讀取和寫入的速度都比MLC更快,而且SLC比MLC更耐用,MLC每單元可擦除1w次,而SLC可擦除10w次,所以,企業級的快閃記憶體產品一般都選用SLC,這也是為什麼企業級產品比家用產品貴很多的原因。
SSD的技術特點
SSD與傳統磁碟相比,第一是沒有機械裝置,第二是由磁介質改為了電介質。在SSD內部有一個FTL(Flash Transalation Layer),它相當於磁碟中的控制器,主要功能就是作地址映射,將flash memory的物理地址映射為磁碟的LBA邏輯地址,並提供給OS作透明訪問。
SSD沒有傳統磁碟的尋道時間和延遲時間,所以SSD可以提供非常高的隨機讀取能力,這是它的最大優勢,SLC類型的SSD通常可以提供超過35000的IOPS,傳統15k的SAS磁碟,最多也只能達到160個IOPS,這對於傳統磁碟來說幾乎就是個天文數字。SSD連續讀的能力相比普通磁碟優勢並不明顯,因為連續讀對於傳統磁碟來說,並不需要尋道時間,15k的SAS磁碟,連續讀的吞吐能力可以達到130MB,而SLC類型的SSD可以達到170-200MB,我們看到在輸送量方面,SSD雖然比傳統磁碟高一些,但優勢雖然並不明顯。
SSD的寫操作比較特殊,SSD的最小寫入單元為4KB,稱為頁(page),當寫入空白位置時可以按照4KB的單位寫入,但是如果需要改寫某個單元時,則需要一個額外的擦除erase)動作,擦除的單位一般是128個page512KB),每個擦除單元稱為塊block)。如果向一個空白的page寫入資訊時,可以直接寫入而無需擦除,但是如果需要改寫某個儲存單元page)的資料,必須首先將整個block讀入緩衝,然後修改資料,並擦除整個block的資料,最後將整個block寫入,很顯然,SSD改寫資料的代價很高,SSD的這個特性,我們稱之為erase-before-write。
經過測試,SLC SSD的隨即寫效能可以達到3000個左右的IOPS,連續寫的輸送量可以達到170MB,這個資料還是比傳統磁碟高出不少。但是,隨著SSD的不斷寫入,當越來越多的資料需要被改寫時,寫的效能就會逐步下降。經過我們的測試,SLC在這個方面要明顯好於MLC,在長時間寫入後,MLC隨機寫IO下降得非常厲害,而SLC表現則比較穩定。為瞭解決這個問題,各個廠商都有很多策略來防止寫效能下降的問題。
wear leveling
因為SSD存在“寫磨損”的問題,當某個單元長時間被反覆擦寫時比如Oracle redo),不僅會造成寫入的效能問題,而且會大大縮短SSD的使用壽命,所以必須設計一個均衡負載的演算法來保證SSD的每個單元能夠被均衡的使用,這就是wear leveling,稱為損耗均衡演算法。
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,二是寫入的速度會比較快(省略了擦除的動作)。
Wear leveling分為兩種:動態損耗均衡和靜態損耗均衡,兩者的原理一致,區別在於動態演算法只會處理動態資料,比如資料改寫時才會觸發資料移轉的動作,對待用資料不起作用,而靜態演算法可以均衡待用資料,當背景工作發現損耗很低的待用資料塊時,將其遷移到其他資料庫塊上,將這些塊放入空閑池中使用。從均衡的效果來看,靜態演算法要好於動態演算法,因為幾乎所有的block都可以被均衡的使用,SSD的壽命會大大延長,但是靜態演算法的缺點是當資料移轉時,可能會導致寫效能下降。
寫入放大
因為SSD的erase-before-write的特性,所以就出現了一個寫入放大的概念,比如你想改寫4K的資料,必須首先將整個擦除塊512KB)中的資料讀出到緩衝中,改寫後,將整個塊一起寫入,這時你實際寫入了512KB的資料,寫入放大係數是128。寫入放大最好的情況是1,就是不存在放大的情況。
Wear leveling演算法可以有效緩解寫入放大的問題,但是不合理的演算法依然會導致寫入放大,比如使用者需要寫入4k資料時,發現free block pool中沒有空白的block,這時就必須在data block pool中選擇一個包含無效資料的block,先讀入緩衝中,改寫後,將整個塊一起寫入,採用wear leveling演算法依然會存在寫入放大的問題。
通過為SSD預留更多空間,可以顯著緩解寫入放大導致的效能問題。根據我們的測試結果,MLC SSD在長時間的隨機寫入後,效能下降很明顯隨機寫IOPS甚至降低到300)。如果為wear leveling預留更多空間,就可以顯著改善MLC SSD在長時間寫操作之後的效能下降問題,而且保留的空間越多,效能提升就越明顯。相比較而言,SLC SSD的效能要穩定很多IOPS在長時間隨機寫後,隨機寫可以穩定在3000 IOPS),我想應該是SLC SSD的容量通常比較小32G和64G),而用於wear leveling的空間又比較大的原因。
資料庫IO特點分析
IO有四種類型:連續讀,隨機讀,隨機寫和連續寫,連續讀寫的IO size通常比較大128KB-1MB),主要衡量輸送量,而隨機讀寫的IO size比較小(小於8KB),主要衡量IOPS和回應時間。資料庫中的全表掃描是連續讀IO,索引訪問則是典型的隨機讀IO,記錄檔是連續寫IO,而資料檔案則是隨機寫IO。
資料庫系統基於傳統磁碟訪問特性來設計,最大特點是記錄檔採用sequential logging,資料庫中的記錄檔,要求必須在事務提交時寫入到磁碟,對回應時間的要求很高,所以設計為順序寫入的方式,可以有效降低磁碟尋道花費的時間,減少延遲時間。記錄檔的順序寫入,雖然是物理位置是連續的,但是並不同於傳統的連續寫類型,記錄檔的IO size很小通常小於4K),每個IO之間是獨立的磁頭必須抬起來重新尋道,並等待磁碟轉動到相應的位置),而且間隔很短,資料庫通過log buffer緩衝)和group commit的方式批量提交)來達到提高IO size的大小,並減少IO的次數,從而得到更小的響應延遲,所以記錄檔的順序寫入可以被認為是“連續位置的隨機寫入”,更關注IOPS,而不是輸送量。
資料檔案採用in place uddate的方式,意思是資料檔案的修改都是寫入到原來的位置,資料檔案不同於記錄檔,並不會在事務commit時寫入資料檔案,只有當資料庫發現dirty buffer過多或者需要做checkpoint動作時,才會重新整理這些dirty buffer到相應的位置,這是一個非同步過程,通常情況下,資料檔案的隨機寫入對IO的要求並不是特別高,只要滿足checkpoint和dirty buffer的要求就可以了。
SSD的IO特點分析
1.隨機讀能力非常好,連續讀效能一般,但比普通SAS磁碟好。
2.不存在磁碟尋道的延遲時間,隨機寫和連續寫的響應延遲差異不大。
3.erase-before-write特性,造成寫入放大,影響寫入的效能。
4.寫磨損特性,採用wear leveling演算法延長壽命,但同時會影響讀的效能。
5.讀和寫的IO響應延遲不對等讀要大大好於寫),而普通磁碟讀和寫的IO響應延遲差異很小。
6.連續寫比隨機寫效能好,比如1M順序寫比128個8K的隨即寫要好很多,因為隨即寫會帶來大量的擦除。
基於SSD的上述特性,如果將資料庫全部放在SSD上,可能會有以下的問題:
1.記錄檔sequential logging會反覆擦寫同一位置,雖然有損耗均衡演算法,但是長時間寫入依然會導致效能下降。
2.資料檔案in place update會產生大量的隨機寫入,erase-before-write會產生寫入放大。
3.資料庫讀寫混合型應用,存在大量的隨機寫入,同時會影響讀的效能,產生大量的IO延遲。
基於SSD的資料庫最佳化法則:
基於SSD的最佳化就是解決erase-before-write產生的寫入放大的問題,不同類型的IO分離,減少寫操作帶來的效能影響。
1.將sequential logging修改為In-page logging,避免對相同位置的反覆擦寫。
2.通過緩衝寫入的方式將大量的in-place update隨機寫入合并為少量順序寫入。
3.利用SSD隨機讀寫能力高的特點,減少寫增加讀,從而達到整體效能的提升。
In-page logging
In-page logging是基於SSD對資料庫sequential logging的一種最佳化方法,資料庫中的sequential logging對傳統磁碟是非常有利的,可以大大提高回應時間,但是對於SSD就是噩夢,因為需要對同一位置反覆擦寫,而wear leveling演算法雖然可以平衡負載,但是依然會影響效能,併產生大量的IO延遲。所以In-page logging將日誌和資料合併,將日誌順序寫入改為隨機寫入,基於SSD對隨機寫和連續寫IO響應延遲差異不大的特性,避免對同一位置反覆擦寫,提高整體效能。
In-page logging基本原理:在data buffer中,有一個in-memory log sector的結構,類似於log buffer,每個log sector是與data block對應的。在data buffer中,data和log並不合并,只是在data block和log sector之間建立了對應關係,可以將某個data block的log分離出來。但是,在SSD底層的flash memory中,資料和日誌是存放在同一個block擦除單元),每個block都包含data page和log page。
當日誌資訊需要寫入的時候log buffer空間不足或者事務提交),日誌資訊會寫入到flash memory對應的block中,也就是說日誌資訊是分布在很多不同的block中的,而每個block內的日誌資訊是append write,所以不需要擦除的動作。當某個block中的log sector寫滿的時候,這時會發生一個動作,將整個block中的資訊讀出,然後應用block中的log sector,就可以得到最新的資料,然後整個block寫入,這時,block中的log sector是空白的。
在in-page logging方法中,data buffer中的dirty block是不需要寫入到flash memory中的,就算dirty buffer需要被交換出去,也不需要將它們寫入flash memory中。當需要讀取最新的資料,只要將block中的資料和日誌資訊合并,就可以得到最新的資料。
In-page logging方法,將日誌和資料放在同一個擦除單元內,減少了對flash相同位置的反覆擦寫,而且不需要將dirty block寫入到flash中,大量減少了in-place update的隨機寫入和擦除的動作。雖然在讀取時,需要做一個merge的操作,但是因為資料和日誌存放在一起,而且SSD的隨機讀取能力很高,in-page logging可以提高整體的效能。
SSD作為寫cache-append write
SSD可以作為磁碟的寫cache,因為SSD連續寫比隨機寫效能好,比如:1M順序寫比128個8K的隨機寫要好很多,我們可以將大量隨機寫合并成為少量順序寫,增加IO的大小,減少IO(擦除)的次數,提高寫入效能。這個方法與很多NoSQL產品的append write類似,即不改寫資料,只追加資料,需要時做合并處理。
基本原理:當dirty block需要寫入到資料檔案時,並不直接更新原來的資料檔案,而是首先進行IO合并,將很多個8K的dirty block合并為一個512KB的寫入單元,並採用append write的方式寫入到一個cache file中儲存在SSD上),避免了擦除的動作,提高了寫入效能。cache file中的資料採用迴圈的方式順序寫入,當cache file空間不足夠時,後台進程會將cache file中的資料寫入到真正的資料檔案中儲存在磁碟上),這時進行第二次IO合并,將cache file內的資料進行合并,整合成為少量的順序寫入,對於磁碟來說,最終的IO是1M的順序寫入,順序寫入只會影響輸送量,而磁碟的輸送量不會成為瓶頸,將IOPS的瓶頸轉化為輸送量的瓶頸,從而提升了整體系統能力。
讀取資料時,必須首先讀取cache file,而cache file中的資料是無序存放的,為了快速檢索cache file中的資料,一般會在記憶體中為cache file建立一個索引,讀取資料時會先查詢這個索引,如果命中查詢cache file,如果沒有命中,再讀取data file普通磁碟),所以,這種方法實際不僅僅是寫cache,同時也起到了讀cache的作用。
但是這種方法並不適合記錄檔的寫cache,雖然記錄檔也是append write,但是因為記錄檔的IO size比較小,而且必須同步寫入,無法做合并處理,所以效能提升有限。
SSD作為讀cache-flashcache
因為大部分資料庫都是讀多寫少的類型,所以SSD作為資料庫flashcache是最佳化方案中最簡單的一種,它可以充分利用SSD讀效能的優勢,又避免了SSD寫入的效能問題。實現的方法有很多種,可以在讀取資料時,將資料同時寫入SSD,也可以在資料被刷出buffer時,寫入到SSD。讀取資料時,首先在buffer中查詢,然後在flashcache中查詢,最後讀取datafile。
SSD作為flashcache與memcache作為資料庫外部cache的最大區別在於,SSD掉電後資料是不丟失的,這也引起了另外一個思考,當資料庫發生故障重啟後,flashcache中的資料是有效還是無效?如果是有效,那麼就必須時刻保證flashcache中資料的一致性,如果是無效的,那麼flashcache同樣面臨一個預熱的問題這與memcache掉電後的問題一樣)。目前,據我所知,基本上都認為是無效的,因為要保持flashcache中資料的一致性,非常困難。
flashcache作為記憶體和磁碟之間的二級cache,除了效能的提升以外,從成本的角度看,SSD的價格介於memory和disk之間,作為兩者之間的一層cache,可以在效能和價格之間找到平衡。
總結
隨著SSD價格不斷降低,容量與效能不斷提升,SSD取代磁碟只是個時間問題。