1. 程式人生 > >關於NVMe SSD以及其IO效能抖動和blktrace工具

關於NVMe SSD以及其IO效能抖動和blktrace工具

關於SSD

企業SSD市場按照介面協議主要分為SATA SSD,PCIe SSD和NVMe SSD,其中SATA SSD沿用了傳統的HDD使用的SATA協議,在企業應用和伺服器相容性上具有優勢; PCIe SSD則一般使用私有協議,處於比較小眾的產品;NVMe SSD則在PCIe介面上使用新的標準協議NVMe,由於NVMe由大廠Intel推出並交由nvmexpress組織推廣,現在被全球大部分儲存企業採納,如memblaze,huawei,samsung都推出了相關的產品。

  1. SSD工作原理

    SSD主要由SSD控制器,FLASH儲存陣列,如下圖:
    1.png
    SSD主控通過若干個通道(channel)並行操作多塊FLASH顆粒,類似RAID0,可以提高底層的頻寬。假設主控與FLASH顆粒之間有8個通道,每個通道上掛載了一個快閃記憶體顆粒,HOST與FLASH之間資料傳輸速率為200MB/s。該快閃記憶體顆粒Page大小為8KB,FLASH page的讀取時間為Tr=50us,平均寫入時間為Tp=800us,8KB資料傳輸時間為Tx=40us。那麼底層讀取最大頻寬為(8KB/(50us+40us))8 = 711MB/s,寫入最大頻寬為(8KB/(800us+40us))

    8 = 76MB/s。從上可以看出,要提高底層頻寬,可以增加底層並行的顆粒數目,也可以選擇速度快的FLASH顆粒(或者讓速度慢的顆粒變快,比如MLC配成SLC使用)。

  2. NVMe Command

    NVMe Host(Server)和NVMe Controller(SSD)都是通過NVMe Command進行資訊互動。NVMe Spec中定義了NVMe Command的格式,可以看到,NVMe Command佔用64位元組。其中Command的前4個位元組規定如下。Command Identifier作為識別這個Command的標誌,Opcode通常包含Command型別(如讀寫,identify等)。
    NVMe Command分為Admin Command和IO Command兩大類,前者主要是用於配置,後者用於資料傳輸。

  3. Nvme與普通盤差異

    Nmve ssd與SATA SSD差異:
    2.png
    nmve ssd與SATA SSD的IO棧差異:
    3.png

  4. 關於效能抖動

    SSD具有很高的IO效能,但是效能穩定性不如磁碟。
    SSD效能發生變化的一個重要因素是內部GC(垃圾回收)機制的影響。
    GC會導致SSD效能發生變化,NAND Flash上的資料佈局方式會對GC效能造成影響,其本質問題是資料遷移與使用者IO之間的資源競爭。
    SSD效能不穩定的因素:
     NAND介質本身的Bit Error;
     讀與寫、擦除的衝突;
     Read Disturb、GC等問題導致效能變差。
    從外在表現來看,Bit Error的增多會導致SSD在使用過程中出現效能抖動問題,尤其是隨著使用壽命的耗盡,SSD效能會發生明顯的變化。另外在不同的IO 模式下,效能也不盡相同,有些SSD甚至會存在寫後讀的問題,緊隨寫之後讀延遲會變得很大,達到毫秒級,這是內部IO衝突導致的。另外在同一區域大量讀之後,也可能發現效能會出現抖動,這也是由於內部的Read Disturb機制開始工作了,會與使用者IO發生競爭,從而導致效能抖動,甚至下降。
    當讀請求和擦除請求落在了同一個通道的相同Die上,那麼讀請求將會由於擦除操作而被迫等待。NAND Flash的擦除操作基本上在2ms以上,如果發生這種衝突,那麼IO的延遲將會從100us提升到2ms以上,從而發生嚴重的延遲。為解決這個問題,現在有些NAND也會提供Erase Suspend的功能,通過該命令讓擦除操作暫停,讓讀操作先進行,從而降低讀延遲。
    NAND Flash存在Read Disturb的問題,當NANDFlash一個區域被重複讀之後,其Bit Error將會上升。為了解決該問題,SSD內部的Firmware會進行Read Disturb的處理。一個區域被重複讀取之後,會進行資料搬移操作,該操作過程類似於Garbage Collection過程。一旦該過程被觸發之後,SSD內部的IO請求數量將會上升,從而對讀請求造成一定的影響,導致效能降低及抖動。

  5. GC

    機械硬碟中檔案系統可以直接將新資料寫入到舊資料儲存的位置,可以直接覆蓋舊資料。在固態硬碟中,如果想讓儲存無用資料的塊寫入新資料,就需要先把整個塊刪除,才可以寫入新的資料
    固態硬碟並不具備直接覆蓋舊資料的能力。固態硬碟GC(垃圾回收)是指把現存資料重新轉移到其他快閃記憶體位置,並且把一些無用的資料徹底刪除的過程。
    SSD盤中資料寫入的方式,以頁面為單位寫入,刪除資料以塊為單位。要刪除無用的資料,先需要把一個塊內包含有用的資料先複製貼上到全新塊中的頁面內,這樣原來塊中包含的無用資料才能夠以塊為單位刪除。刪除後,才能夠寫入新的資料,在擦除之前是無法寫入新資料的。

  6. 寫放大

    SSD寫放大問題,當寫入新資料時,如果SSD控制器找不到可以寫入的page時,會執行GC過程,然後GC機制會將一些block中的有效資料合併寫入其他的block中,然後將這些block的無效資料擦出,再將新資料寫入到這些block中,而在整個過程中除了要寫入使用者的資料之外,實際上SSD還寫入了一些其他block合併過來的資料,所以這就叫寫入放大。

  7. Trim指令

    Trim指令也叫disable delete notify(禁用刪除通知),是微軟聯合各大SSD廠商所開發的一項技術,屬於ATA8-ACS規範的技術指令。
    TRIM(或者DISCARD)的出現主要為了提高SSD垃圾資源的回收效率以及減少寫入放大的發生。SD而言TRIM的最大作用是清空待刪除的無效資料,在SSD執行讀、擦、寫步驟的時候,預先把擦除的步驟先做了,這樣才能發揮出SSD的效能,通常SSD掉速很大一部分原因就是待刪除的無效資料太多,每次寫入的時候主控都要先做清空處理,所以效能受到了限制。
    在檔案系統上刪除某個檔案時候,簡單的在邏輯資料表內把儲存要刪除的資料的位置標記為可用而已,而並不是真正將磁碟上的資料給刪除掉。使用機械硬碟的系統根本就不需要向儲存裝置傳送任何有關檔案刪除的訊息,系統可以隨時把新資料直接覆蓋到無用的資料上。
    固態硬碟只有當系統準備把新資料要寫入那個位置的時候,固態硬碟才意識到原來這寫資料已經被刪除。而如果在這之前,SSD執行了GC操作,那麼GC會把這些實際上已經刪除了的資料還當作是有效資料進行遷移寫入到其他的block中,這是沒有必要的。
    在沒有Trim的情況下,SSD無法事先知道那些被‘刪除’的資料頁已經是‘無效’的,必須到系統要求在相同的地方寫入資料時才知道那些資料可以被擦除,這樣就無法在最適當的時機做出最好的優化,既影響GC的效率(間接影響效能),又影響SSD的壽命。

  8. SSD的個性

    全盤順序寫之後的順序寫效能會比較高,但是在全盤隨機寫之後的順序寫效能會略差。原因在於NAND上的資料佈局初始條件的不同,GC行為會發生差異,從而導致後面的業務IO效能發生變化。
    對於SSD效能可以測試一下SSD使用率達到80%以上時SSD的效能。

  9. IO瓶頸定位工具blktrace

    關於blktrace, Blktrace是一個使用者態的工具,用來收集磁碟IO資訊中當IO進行到塊裝置層(block層,所以叫blk trace)時的詳細資訊(如IO請求提交,入隊,合併,完成等等一些列的資訊).
    blktrace是一個針對linux核心中塊裝置I/O層的跟蹤工具,是由Linux核心塊裝置層的維護者開發的,目前已經整合到核心2.6.17及其之後的核心版本中。通過使用這個工具,使用者可以獲取I/O請求佇列的各種詳細的情況,包括進行讀寫的程序名稱、程序號、執行時間、讀寫的物理塊號、塊大小等等,是一個Linux下分析I/O相關內容的很好的工具
    能記錄I/O所經歷的各個步驟,從中可以分析是IO Scheduler慢還是硬體響應慢。
    使用blktrace需要掛載debugfs
    mount -t debugfs debugfs /sys/kernel/debug
    blktrace -d /dev/nvme0n1 -o test1
    檔案裡面存的是二進位制資料,需要blkparse來解析
    或者直接:
    blktrace -d /dev/nvme0n1 -o - | blkparse -i -
    以上命令可以直接通過:btrace /dev/nvme0n1來實現。
    blkparse只是將blktrace資料轉成可以人工閱讀的格式,由於資料量通常很大,人工分析並不輕鬆,btt是對blktrace資料進行自動分析的工具。
    btt不能分析實時資料,只能對blktrace儲存的資料檔案進行分析

  10. btt使用

#blktrace -w 100 -d /dev/nvme0n1 
把原本按CPU分別儲存的檔案合併成一個,檔名為nvme.bin:
# blkparse -i nvme0n1 -d nvme0n1.bin
$ btt -i nvme0n1.log.bin
輸出如下:

==================== All Devices ====================
ALL MIN AVG MAX N

Q2Q 0.000000001 0.000339658 0.031445634 694894
Q2G 0.000000124 0.000000460 0.000025725 694895
G2I 0.000000185 0.000068326 0.079106703 694864
I2D 0.000000512 0.000004411 0.000055384 694864
D2C 0.000058013 0.593889493 1.777582340 692199
Q2C 0.000062422 0.593962697 1.781217295 692199

  1. blkiomon
使用blkiomon來動態顯示IO棧情況,命令如下:。
blktrace /dev/nvme0n1 -a issue -a complete -w 180  -o - |  blkiomon -I 10 -h -
其中和BLKTRACE相關的概念說明如下:
  1. I/O請求底層相關概念
一個I/O請求進入block layer之後,可能會經歷下面的過程:
       Remap: 可能被DM(Device Mapper)或MD(Multiple Device, Software RAID) remap到其它裝置
       Split: 可能會因為I/O請求與扇區邊界未對齊、或者size太大而被分拆(split)成多個物理I/O
       Merge: 可能會因為與其它I/O請求的物理位置相鄰而合併(merge)成一個I/O
       被IO Scheduler依照排程策略傳送給driver
       被driver提交給硬體,經過HBA、電纜(光纖、網線等)、交換機(SAN或網路)、最後到達儲存裝置,裝置完成IO請求之後再把結果發回。
Q – 即將生成IO請求
G – IO請求生成
I – IO請求進入IO Scheduler佇列
D – IO請求進入driver
C – IO請求執行完畢
Q2G – 生成IO請求所消耗的時間,包括remap和split的時間;
G2I – IO請求進入IO Scheduler所消耗的時間,包括merge的時間;
I2D – IO請求在IO Scheduler中等待的時間;
D2C – IO請求在driver和硬體上所消耗的時間;
Q2C – 整個IO請求所消耗的時間(Q2I + I2D + D2C = Q2C),相當於iostat的await。
其中D2C可以作為硬體效能的指標;
I2D可以作為IO Scheduler效能的指標。
  1. 參考
nvme協議
http://www.nvmexpress.org/resources/specifications/
SSD工作原理
http://www.ssdfans.com/?p=131
SSD的GC和TRIM、寫入放大以及效能評測
http://blog.csdn.net/scaleqiao/article/details/50511279
nvmexpress官方
http://www.nvmexpress.org/