一、背景
在kvm虛擬機ubuntu操作系統大數據平臺測試的過程中,遭遇了磁盤I/O性能的瓶頸,因有cpu綁核操作,故有做隔核操作驗證是否是綁核影響的磁盤I/O,后又對磁盤進行透傳以及掛內存盤等操作;
二、磁盤介紹
2.1 磁盤類型:
HDD
HDD硬盤也就是我們常常說的機械硬盤,機械硬盤是傳統的盤片+磁頭的工作原理,數據都是存儲在盤片上面,磁頭在盤片上面“做運動”來讀取和處理數據信息。
SSD
SSD由控制單元和存儲單元(FLASH芯片、DRAM芯片)組成,固態硬盤的數據讀取速度非常的快。
影響磁盤的幾個參數包含:總線、協議、接口。
2.2 總線:
SAS總線:
SATA總線:
PCIe總線:
在數據傳輸速率表現層面,我們可以簡單地理解為:PCIe4.0 > PCIe3.0 > ASTA3.0 > SAS3.0
2.3 協議:
AHCI協議:
NVMe協議:
SCSI協議:(不常用)
在數據傳輸速率表現層面,我們可以簡單地理解為:NVMe協議傳輸速度比AHCI協議更快。
2.4 接口:
2.5 磁盤陣列:
2.5.1 磁盤陣列介紹
磁盤陣列(Redundant Arrays of Independent Disks,RAID)是由很多塊獨立的磁盤組合成一個容量巨大的磁盤組,利用個別磁盤提供數據所產生加成效果提升整個磁盤系統效能。它利用這項技術,將數據切割成許多區段,分別存放在各個硬盤上。在數據重構時,可將數據經計算后重新置入新硬盤中。從用戶觀點看,磁盤陣列雖然是由幾個、幾十個甚至上百個盤組成,但仍可認為是一個單一磁盤。
2.5.2 磁盤陣列組成
Raid卡:這是實現RAID功能的核心組件,它可以劃分RAID,讓很多磁盤驅動器同時傳輸數據,而這些磁盤驅動器在邏輯上又是一個磁盤驅動器。
CPU:用于處理RAID卡上的數據和指令。
IO處理器:用于處理輸入輸出請求,將數據從磁盤讀取到緩存中,或者將數據從緩存寫入磁盤。
SCSI控制器:用于控制SCSI總線上的設備,實現設備之間的數據傳輸。
SCSI連接器:用于連接SCSI設備和主機系統。
cache:用于存儲暫時不用的數據和指令,提高系統的性能。
2.5.3 常見的Raid類型
RAID 0:
RAID 1:
RAID 5:
RAID 6:
RAID 10:
2.5.4 影響磁盤陣列速度和性能的因素
磁盤陣列的設置:如果磁盤陣列沒有正確設置,可能無法實現最佳的性能。
網絡連接速度:磁盤陣列設備的速度可能受到網絡連接速度的限制。
磁盤過載:如果磁盤陣列中的磁盤過載,速度也可能會受到影響。
軟件故障:磁盤陣列設備中的軟件可能出現故障,導致性能下降。
磁盤污染:磁盤陣列中的磁盤可能受到污染,導致性能下降。
傳輸帶寬:傳輸帶寬指的是硬盤或設備在傳輸數據的時候數據流的速度,主要取決于磁盤陣列的構架、通道的大小以及磁盤的個數。
注:磁盤的性能一般使用IOPS表示
IOPS:固態硬盤的IOPS是指每秒輸入/輸出操作數,表示固態硬盤每秒可以處理多少個讀寫請求。決定IOPS的主要取決于磁盤陣列RAID類型、CACHE命中率以及磁盤個數。磁盤陣列的速度和性能可能受到多種因素的影響,包括硬件、軟件、網絡等多個方面。
三、掛載內存盤
3.1 查看虛擬機硬盤綁定情況
ps axu| grep qemu
3.2 硬盤讀寫性能測試(filename:待測試路徑 HDD硬盤隨機讀寫測試性能一般在4M/s左右)
fio -filename=/vdb_data/test_randread -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=4k -size=10G -numjobs=10 -runtime=60 -group_reporting -name=mytest
參數解釋
-filename=/vdb_data/test_randread:指定測試文件的路徑和名稱為/vdb_data/test_randread。
-direct=1:使用直接I/O模式,即跳過系統緩存,直接讀寫磁盤。
-iodepth 1:每個作業的I/O深度為1,即每個作業在隊列中只有一個I/O請求。
-thread:使用線程模式執行測試任務。
-rw=randrw:使用隨機讀寫模式進行測試,即同時進行隨機讀和隨機寫操作。
-ioengine=psync:指定使用psync I/O引擎。
-bs=4k:設置每個I/O請求的塊大小為4KB。
-size=10G:指定測試文件的大小為10GB。
-numjobs=10:指定并發作業數為10,即同時執行10個測試任務。
-runtime=60:設置測試運行時間為60秒。
-group_reporting:匯總所有作業的結果報告。
-name=mytest:指定測試任務的名稱為mytest,用于標識這個測試任務。
3.3 硬盤透傳
虛擬機磁盤透傳是指將物理主機上的磁盤直接映射給虛擬機使用,而不是通過虛擬機軟件(如VMware、VirtualBox)創建虛擬磁盤文件。這樣做可以提高性能,減少虛擬化層的開銷,適用于一些對性能要求較高的應用場景。
3.3.1 以下是在一些常見虛擬化平臺上實現磁盤透傳的步驟:
KVM/QEMU(測試的情況)
1、編輯虛擬機的XML配置文件,添加類似如下的配置:
vim /vmimages/passthough-disk.xml
<disk type='block' device='disk'><driver name='qemu' type='raw' cache='none'/><source dev='/dev/nvme4n1'/><target dev='vdd' bus='virtio'/>
</disk>
其中/dev/nvme4n1是要透傳的物理磁盤設備。
2、使用virsh工具重新加載配置文件使更改生效:
#掛載透傳硬盤
virsh attach-device vm1 /vmimages/passthough-disk.xml
#取消掛載透傳硬盤
virsh detach-device vm1 /vmimages/passthough-disk.xml# vm1是虛擬機名
VMware vSphere/ESXi
1、在ESXi主機上將物理磁盤添加到存儲適配器中。
2、在虛擬機設置中選擇添加硬件 - 存儲控制器 - 硬盤。
3、選擇“使用一個已經存在的磁盤”,然后選擇要透傳的物理磁盤。
4、完成虛擬機設置并啟動虛擬機,系統會識別并掛載透傳的物理磁盤。
Microsoft Hyper-V
1、在Hyper-V管理器中選擇目標虛擬機,右鍵點擊設置。
2、選擇添加硬件,然后選擇物理硬盤。
3、選擇要透傳給虛擬機的物理磁盤。
4、完成虛擬機設置并啟動虛擬機,系統會識別并掛載透傳的物理磁盤。
3.4 掛載內存盤
mount -t tmpfs -o size=40G tmpfs /mnt/tmp/
-t tmpfs:指定掛載的是內存盤
-o size=40G tmpfs;指定掛載內存盤大小
開機自動掛載
tmpfs /mnt/tmp/ tmpfs size=40G 0 0
內存盤讀寫性能測試(去除-direct參數,否則不能運行):
fio -filename=/mnt/tmp/test_randread -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=4k -size=2G -numjobs=1 -runtime=600 -group_reporting -name=mytest
3.5 隔核測試
1、隔核操作
sudo vim /etc/default/grub
增加以下內容
# 隔核2-79,iommu=pt,intel_iommu=on
GRUB_CMDLINE_LINUX_DEFAULT="isolcpus=2-79 iommu=pt intel_iommu=on"
使改動生效
update-grubreboot
2、指定內核測試磁盤性能
taskset -c 3(指定xx核) fio -filename=/ssd_test/test_randread -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=10G -numjobs=1 -runtime=60 -group_reporting -name=mytest
3、給予線程高權限,防止因為out of memory被宿主機kill:
ps aux | grep qemu(獲取虛擬機得進程id)echo -1000 > /proc/進程id/oom_score_adj
占用指定內存空間以達到極限測試效果的程序
def allocate_memory(size_in_gb):# 分配指定GB數的內存空間num_bytes = size_in_gb * (1024**3) # 轉換GB到字節try:# 使用bytearray創建一個大數組big_array = bytearray(num_bytes)print(f"Successfully allocated {size_in_gb} GB of memory")return big_arrayexcept MemoryError:print(f"Failed to allocate {size_in_gb} GB of memory. Not enough resources.")if __name__ == "__main__":size = 40 # 指定想要分配的內存大小(GB)memory_block = allocate_memory(size)# 在此處加入任何想要進行的處理# ...input("Press Enter to release the allocated memory and exit the program.")