關於ssd儲存原理的介紹
眾所周知SSD的讀寫速度遠比hdd磁碟要快,理解ssd的工作原理使我們開發處高效儲存方案。
linux 相關指令
fstrim --fstab --verbose ## 回收(discard)檔案系統上對應磁碟未使用的塊
blkdiscard /dev/nvme1n1 ## 回收並擦除(discard)整個SSD塊裝置
wipefs -a /dev/nvme1n1 ## 擦除(erase)檔案系統的簽名
fstrim
fstrim命令實際可以視為手動對SSD磁碟下發TRIM指令。使用-v引數可以直接檢視TRIM回收擦除空間的大小。fstrim是針對已掛載的檔案系統的SSD分割槽
root@xxxx:~# fstrim --help
Usage:
fstrim [options] <mount point>
Discard unused blocks on a mounted filesystem.
Options:
-a, --all trim all supported mounted filesystems
-A, --fstab trim all supported mounted filesystems from /etc/fstab
-o, --offset <num> the offset in bytes to start discarding from
-l, --length <num> the number of bytes to discard
-m, --minimum <num> the minimum extent length to discard
-v, --verbose print number of discarded bytes
-n, --dry-run does everything, but trim
-h, --help display this help
-V, --version display version
For more details see fstrim(8).
以下是執行後返回的結果,以NVMe 為列
/home: 32.5 GiB (313011310592 bytes) trimmed on /dev/mapper/gat204--vg-root
/boot/efi: 102.2 MiB (607301632 bytes) trimmed on /dev/nvme1n1p1
/boot: 732.5 MiB (825778176 bytes) trimmed on /dev/nvme1n1p2
/: 60.7 GiB (65154805760 bytes) trimmed on /dev/mapper/gat204--vg-swap_1
ubuntu與debian的systemd 服務可以定時執行fstrim,省去手寫crontab指令碼工作。
systemctl status fstrim.timer ##查詢服務狀態
systemctl enable fstrim.timer ##開啟定時TRIM功能
blkdiscard
blkdiscard用於擦除(discard)SSD裝置扇區,和fstrim不同這條命令直接用在塊裝置上,預設擦除整個塊裝置的所有扇區。
root@xxxx:~# blkdiscard -help
Usage:
blkdiscard [options] <device>
Discard the content of sectors on a device.
Options:
-o, --offset <num> offset in bytes to discard from
-l, --length <num> length of bytes to discard from the offset
-p, --step <num> size of the discard iterations within the offset
-s, --secure perform secure discard
-z, --zeroout zero-fill rather than discard
-v, --verbose print aligned length and offset
-h, --help display this help
-V, --version display version
For more details see blkdiscard(8).
root@ECSab169d:~# man blkdiscard
擦除(discard)成功後,沒有返回結果
root@xxxx:~# blkdiscard /dev/nvme1n1
root@xxxx:~#
wipefs
wipefs是linux自帶的程式,用來擦除(erase)檔案系統的簽名,不會清空檔案系統或裝置中的任何其他資料。預設情況下, wipefs 不會擦除非整個磁碟裝置上的巢狀分割槽表。為此,需要—force選項。
root@gat204:~# wipefs --help
Usage:
wipefs [options] <device>
Wipe signatures from a device.
Options:
-a, --all wipe all magic strings (BE CAREFUL!)
-b, --backup create a signature backup in $HOME
-f, --force force erasure
-i, --noheadings don't print headings
-J, --json use JSON output format
-n, --no-act do everything except the actual write() call
-o, --offset <num> offset to erase, in bytes
-O, --output <list> COLUMNS to display (see below)
-p, --parsable print out in parsable instead of printable format
-q, --quiet suppress output messages
-t, --types <list> limit the set of filesystem, RAIDs or partition tables
-h, --help display this help
-V, --version display version
Available output columns:
UUID partition/filesystem UUID
LABEL filesystem LABEL
LENGTH magic string length
TYPE superblok type
OFFSET magic string offset
USAGE type description
DEVICE block device name
For more details see wipefs(8).
檢查SSD是否支援TRIM
##可以通過 /sys/block 下的資訊來判斷 SSD 支援 TRIM, discard_granularity 非 0 表示支援。
# cat /sys/block/sda/queue/discard_granularity
0
# cat /sys/block/nvme0n1/queue/discard_granularity
512
儲存元器件(快閃記憶體顆粒類別)
SSD的儲存是NAND-Flash快閃記憶體顆粒,分為SLC、MLC和QLC四種。可以粗略地把快閃記憶體顆粒理解成是一個電容加上電壓計的組合。一個電容能存放一個位元的資料,電壓計使電容能區分不同電壓,不同的電壓能存放更多的位元資料。
SLC(Single-Level Cell): 每個Cell單元儲存1bit資訊,也就是隻有0、1兩種電壓變化,結構簡單,電壓控制也快速,反映出來的特點就是壽命長,效能強,P/E壽命在1萬到10萬次之間,但缺點就是容量低而成本高.
MLC(Multi-Level Cell): 每個cell單元儲存2bit資訊,需要更復雜的電壓控制,有00,01,10,11四種變化,這也意味著寫入效能、可靠效能降低了。其P/E壽命根據不同製程在3000-5000次不等.
TLC(Triple-Level Cell):每個cell單元儲存3bit資訊,電壓從000到001有8種變化,容量比MLC再次增加1/3,成本更低,但是架構更復雜,P/E程式設計時間長,寫入速度慢,P/E壽命也降至1000-3000次,部分情況會更低.壽命短只是相對而言的,通常來講,經過重度測試的TLC顆粒正常使用5年以上是沒有問題的.
QLC(Quad-Level Cell):QLC或者可以叫4bit MLC,電壓有16種變化,但是容量能增加33%,就是寫入效能、P/E壽命與TLC相比會進一步降低。具體的效能測試上,美光有做過實驗。讀取速度方面,SATA介面中的二者都可以達到540MB/S,QLC表現差在寫入速度上,因為其P/E程式設計時間就比MLC、TLC更長,速度更慢,連續寫入速度從520MB/s降至360MB/s,隨機效能更是從9500 IOPS降至5000 IOPS,損失將近一半.
這四類當中,SLC的效能最優,價格超高;MLC效能夠用,價格適中為消費級SSD應用主流;TLC綜合性能最低,價格最便宜,但可以通過高效能主控、主控演算法來彌補、提高TLC快閃記憶體的效能;QLC出現的時間很早,價格便宜,容量大。
P/E以及其SSD底層儲存結構
P指的是Program(程式設計),E指的是Erease (擦除), 快閃記憶體完全擦寫一次可以稱為1次P/E,因此快閃記憶體的壽命以P/E為單位。和HDD機械硬碟不同,HDD的資料是可以覆寫的(Overwrite),而SSD在寫入資料前必須先進行擦除(erase),一般在格式化檔案系統步驟或者SSD出廠配置的過程中,SSD已進行了全盤擦除(erase),因此SSD的首次寫入資料是直接程式設計。
SSD 在快閃記憶體單元中存取資料時有 page 和 block 的概念。SSD 被劃分成很多 block, 而 block 被劃分成很多 page。
NAND-Flash讀寫流程
Page是NAND-Flash單次讀寫單位,大小一般為4K或者4K位元組的倍數,寫操作只能寫到空的 page,而清除資料(Erase) 是以 塊(block) 為單位的。塊的擦除次數有壽命限制,超限制就會變成壞塊。
使用者對SSD的寫入資料操作可以分為兩種型別
1.原來SSD磁碟上沒有資料,寫入資料。
2.SSD磁碟上有資料,對該資料進行修改(包括刪除)。
前者只需把資料直接寫入到空白頁即可,後者則是read-modify-write方式操作,讀取原有page的內容到快取中並進行更新,最後寫入到其他空的page,原有的page置為無效頁。
可以想象對檔案的持續反覆的修改,將會產生大量的無效頁,這就需要“垃圾回收”(Garbage Collection-gc)機制來回收這些無效頁,否則可以寫入空間越來越小。
FTL 和磨損均衡
SSD的主控執行磨損均衡(Wear-Leveling)策略,使SSD磁碟各個塊的擦除次數均勻分攤到各個塊上。就像記憶體MMU一樣,SSD內部使用快閃記憶體轉換層(FTL)存放了邏輯塊地址(Logical Block Address,簡稱 LBA)到物理塊地址(Physical Block Address,簡稱 PBA)的對映。作業系統訪問的硬碟地址,其實都是邏輯地址。只有通過 FTL 轉換之後,才會變成實際的實體地址,找到對應的塊進行訪問。作業系統本身,不需要去考慮塊的磨損程度,只要和操作機械硬碟一樣來讀寫資料就好了。
“垃圾回收”機制
寫入放大(write amplification)
上文提及過資料的反覆修改會產生大量的無效頁,一旦整個塊(block)的空間不足以寫入資料,SSD會將這個塊(block)的資料讀入到快取中,擦除這個塊(block)所中的頁,然後再把快取中已更新的資料寫入進去。這種read-erase-modify-write過程,就好比寫入的資料可能只有一個頁4KB,但實際要擦除並且寫N個頁,稱之為寫入放大。
寫入放大的倍數越大,寫入的速度就越慢。
TRIM指令
TRIM是SSD的ATA-8指令,解決寫入放大的關鍵。
檔案系統在修改或者刪除過程中,傳送給通知給SSD記錄產生的無效頁,間隔一定時間再統一回收擦除所有無效頁,擦除更新無效頁所在的塊(block)。
一方面預留足夠多的空間,避免因空間不足產生寫入放大的情況。另一方面,使用TRIM,在IO閒時回收擦除無效頁,這樣有效保證SSD的效能以及提高壽命。
discard與TRIM的區別
在linux術語中,discard指的就是TRIM
不建議使用linux系統預設的TRIM功能
TRIM功能有兩種方式啟動,一種是連續TRIM,就是直接在檔案系統回收塊的時候直接發TRIM命令,這種方式對效能影響比較大,在fstab掛載的時候把default修改成discard。另外一種是定期執行fstrim批量進行TRIM操作,這樣避免平時的效能影響,不過fstrim的執行時機要選好,畢竟批量TRIM的時候會對其它任務效能影響較大。
根據文章《Ubuntu Doesn’t TRIM SSDs By Default: Why Not and How To Enable It Yourself》提及到
“The kernel implementation of realtime trim in 11.2, 11.3, and 11.4 is not optimized. The spec. calls for trim supporting a vectorized list of trim ranges, but as of kernel 3.0 trim is only invoked by the kernel with a single discard / trim range and with current mid 2011 SSDs this has proven to cause a performance degradation instead of a performance increase. There are few reasons to use the kernels realtime discard support with pre-3.1 kernels. It is not known when the kernels discard functionality will be optimized to work beneficially with current generation SSDs.” [Source]
利用核心方式的discard 方式無法感知對SSD當前效能的影響。
實踐
使用fio測試nvme裸裝置
使用fio對裸裝置直接進行randwrite測試,在超過30分鐘速度由400MiB/s降低至80MiB/s 分析原因得出SSD觸發了放大寫現象,並且由於沒有掛載檔案系統,無法使用fstrim手動回收空間(可以理解成,在沒有檔案系統標記下,SSD也不知道哪些是無效頁),再次進行fio測試速度依然是80MiB/s。使用blkdiscard進行全盤擦除後,速度恢復正常。
參考文獻
《Trim命令》 wiki百科
《淺談分散式儲存之SSD基本原理》滴滴雲
《Linux 下啟用 SSD TRIM 功能》Louis
結束語
當使用fio直接ssd磁碟進行寫入測試後,對磁碟使用blkdiscard可恢復原來的速度。