نحوه تشخیص واقعی بودن دیسک NVMe در سرور مجازی لینوکس
آیا VPS شما واقعاً از NVMe استفاده میکند؟ با استفاده از دستورات lsblk و nvme-cli و تحلیل تأخیر در fio، تفاوت درایور مجازی virtio با سختافزار واقعی را در لینوکس بررسی کنید.
تأیید یک دیسک NVMe در لینوکس در چهار مرحله
برای تأیید یک دیسک NVMe روی یک VPS لینوکسی، چهار بررسی را به ترتیب انجام دهید: lsblk برای نام دستگاه، فلگ rotational در sysfs برای رسانههای چرخشی، nvme list برای یک کنترلر واقعی NVMe، و یک اجرای کوتاه fio برای تنها عددی که یک میزبان نمیتواند آن را جعل کند. سه مورد اول هر کدام یک ثانیه زمان میبرند. مورد آخر تکلیف را روشن میکند، زیرا در اکثر پلتفرمهای VPS، هایپروایزر دیسک فیزیکی را از دید مهمان پنهان میکند.
پروتکل NVMe (مخفف non-volatile memory express) زبانی است که حافظههای فلش از طریق مسیرهای PCIe (مخفف peripheral component interconnect express) با آن صحبت میکنند. این پروتکل جایگزین مسیر SATA و AHCI شد که برای درایوهای چرخشی طراحی شده بودند؛ سرعت آن به این دلیل است که گلوگاه صفبندی بین CPU و فلش را حذف میکند. در داخل یک ماشین مجازی، شما بهندرت مستقیماً با آن پروتکل صحبت میکنید. شما با یک دیسک مجازی که میزبان برای شما اسمبل کرده است در ارتباط هستید، بنابراین نام دستگاه در سیستمعامل مهمان شما، توصیفکننده یک درایور است، نه رسانه موجود در رک.
گام 1: دستور lsblk چه چیزی را نشان میدهد؟
lsblk لیست دستگاههای بلوکی (block devices) را از هسته سیستمعامل میخواند. فلگ -d پارتیشنها را مخفی میکند تا برای هر دیسک تنها یک خط نمایش داده شود.
lsblk -d -o NAME,ROTA,SIZE,TYPE,TRAN,MODELیک VPS از نوع KVM معمولاً خروجی زیر را ارائه میدهد:
NAME ROTA SIZE TYPE TRAN MODEL
vda 0 80G diskسه الگوی نامگذاری، تقریباً تمام سرورهای لینوکسی را پوشش میدهند:
nvme0n1فضای نام 1 روی کنترلر NVMe شماره 0 است. سیستمعامل مهمان شما در حال استفاده از یک دستگاه NVMe است، چه واقعی باشد و چه شبیهسازیشده.sdaلایه SCSI است. دیسکهای SATA و SAS واقعی و همچنین درایور virtio-scsi در این دسته قرار میگیرند.vdaدرایور virtio-blk است؛ درایور بلوکی نیمهمجازی (paravirtual) که اکثر میزبانهای KVM بهصورت پیشفرض از آن استفاده میکنند.
ستون TRAN (انتقال) برای دستگاههای NVMe مقدار nvme و برای دیسکهای SATA که سیستمعامل مهمان مستقیماً میبیند، مقدار sata را نشان میدهد. این ستون معمولاً در virtio-blk خالی است، زیرا هیچ لایه انتقال فیزیکی برای گزارشدهی به سیستمعامل مهمان وجود ندارد. مقدار MODEL نیز به همین دلیل خالی است. خالی بودن رشته مدل (model string) در یک VPS امری عادی است و اطلاعاتی درباره سختافزار زیرین به شما نمیدهد.
گام 2: رد احتمال استفاده از دیسک چرخان
DISK=$(lsblk -dno NAME,TYPE | awk '$2 == "disk" { print $1; exit }')
echo "checking $DISK"
cat "/sys/block/$DISK/queue/rotational"
readlink -f "/sys/block/$DISK"فایل rotational زمانی که هسته سیستمعامل تشخیص دهد دستگاه دارای صفحات چرخان است، مقدار 1 و در غیر این صورت مقدار 0 را در خود نگه میدارد. در سیستمهای bare metal، این مقدار مستقیماً از خود درایو خوانده میشود. در محیط virtio-blk، این مقدار از یک بیت ویژگی (feature bit) که توسط میزبان تنظیم شده است میآید؛ بنابراین مقدار 0 تنها احتمال استفاده از هارد دیسک معمولی را رد میکند و فراتر از آن چیزی را اثبات نمیکند. با این حال، آن را بررسی کنید: مشاهده 1 در محصولی که به عنوان حافظه solid state فروخته شده، یک تناقض آشکار است و این همان مدرکی است که تیم پشتیبانی نمیتواند آن را رد کند.
دستور readlink -f لینک نمادین sysfs را دنبال کرده و گذرگاهی (bus) که دستگاه به آن متصل است را چاپ میکند:
/sys/devices/pci0000:00/0000:00:05.0/virtio2/block/vdaکلمه virtio در آن مسیر، پاسخ شما برای این گام است. یک دستگاه NVMe مسیری شامل nvme ارائه میدهد، مانند /sys/devices/pci0000:00/0000:01:00.0/nvme/nvme0/nvme0n1، و یک دیسک ATA که مستقیماً متصل شده، مسیری شامل ata1 را نمایش میدهد. این همان واقعیتی است که lsblk چاپ میکند، با این تفاوت که مستقیماً از هسته گرفته شده است و نه از یک ستون فرمتشده؛ این موضوع زمانی که فیلد TRAN خالی باشد، بسیار مفید است.
گام 3: پرسوجو از nvme-cli و گذرگاه PCI
sudo apt update
sudo apt install -y nvme-cli pciutils
sudo nvme list || echo "nvme-cli found no NVMe device"
lspci | grep -i -e nvme -e 'non-volatile' || echo "no NVMe controller on this guest's PCI bus"nvme list به ازای هر namespace یک ردیف شامل شماره سریال کنترلر، رشته مدل و نسخه فریمور چاپ میکند. خالی بودن جدول به این معناست که هیچ دستگاه NVMe برای مهمان (guest) شما در دسترس نیست. lspci اگر هیچ خط منطبقی چاپ نکند، همین موضوع را از زاویهای دیگر تأیید میکند: گذرگاه مجازی PCI که مهمان شما میبیند، هیچ کنترلر NVMe را حمل نمیکند. هر دو نتیجهٔ خالی در یک VPS مبتنی بر virtio خروجی عادی محسوب میشوند و هیچکدام دلیلی بر این نیست که میزبان (host) درایو NVMe ندارد.
اگر یک namespace ظاهر شد، nvme-cli فراتر میرود. sudo nvme id-ctrl /dev/nvme0 هویت کنترلر را چاپ میکند و sudo nvme smart-log /dev/nvme0n1 دما، ساعات روشن بودن و درصد استهلاک نوشتن (write endurance) مصرفشده را نمایش میدهد. این دستورات را فقط زمانی اجرا کنید که nvme list واقعاً دستگاهی را فهرست کرده باشد، زیرا هر دو دستور برای باز شدن به یک گره /dev/nvme* واقعی نیاز دارند.
چرا یک میزبان NVMe واقعی همچنان /dev/vda را نشان میدهد
هایپروایزر (hypervisor) تصمیم میگیرد که مهمان (guest) چه مدل دستگاهی را ببیند و این انتخاب مستقل از رسانهٔ زیرین است. سه چیدمان رایج وجود دارد:
- استفاده از virtio-blk یا virtio-scsi روی یک فایل، یک logical volume یا یک ZFS dataset که روی درایوهای NVMe قرار دارد. شما
vdaیاsdaرا میبینید. فضای ذخیرهسازی NVMe است، اما مهمان راهی برای تشخیص این موضوع ندارد. - یک کنترلر NVMe شبیهسازیشده که در مقابل هر نوع فضای ذخیرهسازی قرار میگیرد. شما
nvme0n1را میبینید، حتی اگر دادهها روی یک آرایه SATA یا یک volume شبکه در دو رک آنطرفتر ذخیره شوند. - گذردهی PCIe (PCIe passthrough)، که در آن میزبان یک کنترلر فیزیکی را به یک مهمان اختصاص میدهد. شما یک
nvme0n1واقعی با یک رشته مدل واقعی میبینید. این مورد در پلنهای VPS اشتراکی نادر است، زیرا کارت در این حالت به آن مشتری خاص اختصاص مییابد.
بنابراین نام دستگاه میتواند شما را در هر دو جهت گمراه کند. بدتر اینکه میزبان میتواند یک write-back cache، یک لایه RAID یا یک volume شبکهٔ کپیشده (replicated) را بین عملیات نوشتن شما و حافظهٔ فلش قرار دهد؛ هر یک از این موارد عملکرد دریافتی شما را تغییر میدهد بدون اینکه حتی یک نام در /sys عوض شود. به همین دلیل است که نام دستگاه نقطهٔ شروع بررسی شماست، نه نقطهٔ پایان. اگر هنوز در حال انتخاب پلن هستید، تفاوت بین فضای ذخیرهسازی NVMe و SATA SSD توضیح میدهد که هر سطح واقعاً ارزش پرداخت چه هزینهای را دارد.
صادقانهترین آزمون، سنجش تأخیر (latency) است
ابزار fio (مخفف flexible I/O tester) عملیات خواندن واقعی را روی یک فایل واقعی انجام میدهد و گزارش میدهد که هر عملیات چقدر زمان برده است. خواندنهای تصادفی کوچک (small random reads)، بار کاری مناسب برای این منظور هستند؛ زیرا رفتوبرگشت به رسانه ذخیرهسازی را آشکار میکنند و نمیتوان آنها را با قابلیت read-ahead پوشش داد.
ابتدا فایل تست را ایجاد کنید و مطمئن شوید که این فایلسیستم از I/O بدون بافر (unbuffered) پشتیبانی میکند. --direct=1 فایل را با O_DIRECT باز میکند که باعث دور زدن page cache میشود. بدون این گزینه، شما در واقع سرعت RAM خود را اندازهگیری میکنید و به اعدادی میرسید که هیچ دیسکی قادر به تولید آنها نیست.
sudo apt install -y fio
fio --name=prep --filename=/var/tmp/nvme-check.tmp --size=256M --bs=1M --rw=write --direct=1 --end_fsync=1 > /dev/null \
&& echo "unbuffered writes work here, the timing test is valid" \
|| echo "this filesystem refuses direct=1, so the timing test below will not run"اگر دستور بالا خطای عدم پشتیبانی را چاپ کرد، مسیری که انتخاب کردهاید روی فایلسیستمی قرار دارد که از O_DIRECT پشتیبانی نمیکند. فایلسیستمهای overlay کانتینرها و برخی فایلسیستمهای شبکهای چنین رفتاری دارند. یک دایرکتوری در ریشه فایلسیستم VPS انتخاب کنید و دوباره تلاش کنید. اگر عملیات با موفقیت انجام شد، اندازهگیری را اجرا کنید:
fio --name=randread4k --filename=/var/tmp/nvme-check.tmp --bs=4k --rw=randread \
--direct=1 --iodepth=1 --numjobs=1 --runtime=20 --time_based --group_reporting \
|| echo "fio stopped early, read its first line for the reason"
rm -f /var/tmp/nvme-check.tmpاین اجرا بهصورت هدفمند محدود شده است: یک job، عمق صف (queue depth) برابر با 1، بیست ثانیه زمان و 256 مگابایت داده. این تست دیسک شما را پر نمیکند و باعث نمیشود به دلیل سوءاستفاده (abuse) پرچمگذاری شوید. عمق صف 1 نیز تنظیم صادقانهای برای این پرسش است؛ زیرا صفهای عمیق به یک دستگاه کند اجازه میدهند پشت موازیسازی پنهان شود، در حالی که تأخیر همچنان بالا باقی میماند.
خواندن خروجی fio
دو خط اهمیت دارند. خط خلاصه به شکل read: IOPS=9012, BW=35.2MiB/s است و زیر آن، fio یک بلوک clat چاپ میکند. clat همان تأخیر تکمیل (completion latency) است: زمانی که بین ارسال درخواست خواندن توسط fio و تحویل دادهها توسط هسته (kernel) سپری میشود. مقدار avg را بخوانید و سپس صدک 99.00th را در لیست clat percentiles بررسی کنید. میانگین، کلاس حافظه را به شما نشان میدهد. صدک 99 نشان میدهد که یک همسایه روی همان میزبان، چند وقت یکبار باعث معطلی شما میشود.
زمانی که مقادیر کوچک باشند، fio تأخیر را به میکروثانیه چاپ میکند و در صورت بزرگ بودن مقادیر، به میلیثانیه تغییر وضعیت میدهد. پیش از مقایسه هر چیزی، واحد اندازهگیری را در خط قبل بررسی کنید.
چه اعدادی کلاس NVMe را از کلاس SATA متمایز میکنند
ارقام زیر مقادیر معمول منتشرشده برای خواندن تصادفی 4k در یک job واحد با عمق صف (queue depth) 1 هستند که تا اوت 2026 از مستندات فروشندگان و بنچمارکهای جامعه کاربری جمعآوری شدهاند. اینها بازههایی برای مقایسه هستند، نه اندازهگیریهای انجامشده روی سرور شما.
The data behind this chart
[
{
"label": "Local NVMe",
"avg_latency_us": 110
},
{
"label": "Local SATA SSD",
"avg_latency_us": 320
},
{
"label": "Network block storage",
"avg_latency_us": 900
}
]The data behind this chart
[
{
"label": "Local NVMe",
"iops": "9,000"
},
{
"label": "Local SATA SSD",
"iops": "3,100"
},
{
"label": "Network block storage",
"iops": "1,100"
}
]یک volume محلی NVMe به یک خواندن تصادفی 4k در حدود 110 میکروثانیه پاسخ میدهد و در عمق صف 1 به حدود 9,000 IOPS میرسد. یک SSD محلی SATA در حدود 320 میکروثانیه و 3,100 IOPS قرار دارد. فضای ذخیرهسازی بلوکی متصل به شبکه (Network attached block storage) در حدود 900 میکروثانیه و 1,100 IOPS قرار میگیرد، زیرا پیش از آنکه فلش لمس شود، هر خواندن باید از یک hop شبکه عبور کند.
در عمق صف 1، این دو ستون بیانگر یک واقعیت واحد هستند: وقتی در هر لحظه فقط یک خواندن انجام میشود، throughput صرفاً حاصل تقسیم یک بر latency است. اگر میانگین شما به 110 نزدیکتر است تا به 320 میکروثانیه، شما از فضای ذخیرهسازی کلاس NVMe استفاده میکنید، فارغ از اینکه lsblk چه نامی برای آن دستگاه انتخاب کرده باشد. اگر این مقدار به 900 میکروثانیه نزدیکتر است، چیزی کندتر از فلش محلی در مسیر قرار دارد و کلمه NVMe در صفحه سفارش، در حال توصیف درایوهای میزبان است نه volume شما.
پیش از شکایت، آن را بیش از یک بار اجرا کنید
یک بار اجرا، نمونه است، نه نتیجه. یک VPS دیسکهای خود را به اشتراک میگذارد، بنابراین یک همسایه پرمشغله میتواند تأخیر شما را برای 10 دقیقه دو برابر کند و سپس ناپدید شود. برخی پلتفرمها همچنین اعتبار burst ارائه میدهند که باعث میشود دقایق اولیه هر تست عالی به نظر برسد. همان دستور را سه یا چهار بار در ساعات مختلف روز اجرا کنید و بدترین نتیجه را مقایسه کنید، نه بهترین را. یک اجرای بدِ تکی، ناشی از شرایط لحظهای است. یک الگو، خطایی است که ارزش ارسال تیکت پشتیبانی را دارد و تیکت با پیوست کردن سه خروجی fio دارای مهر زمانی، نتیجه بهتری خواهد داشت. برای تصویر گستردهتری که علاوه بر دیسک، CPU و شبکه را نیز پوشش دهد، اجرای یک بنچمارک کامل VPS از همین نظم برای سایر زیرسیستمها استفاده میکند.
با نتیجه چه کنیم
اگر تأخیر در محدوده NVMe قرار دارد، نگران نام دستگاه نباشید و به سراغ کارهای بعدی بروید. vda یک تنزل رتبه نیست. این سریعترین درایور دیسک مجازی است که اکثر میزبانها ارائه میدهند و دقیقاً همان چیزی است که به آن نیاز دارید.
اگر تأخیر در محدوده ذخیرهسازی شبکه قرار دارد، در حالی که پلن خریداریشده به عنوان NVMe محلی فروخته شده است، شما یک ادعای مشخص و قابل اثبات دارید: دستور دقیق fio، میانگین تأخیر تکمیل و زمانهایی که آن را اجرا کردهاید. این موضوع یک تیکت پشتیبانی است، نه یک بحث در انجمن. پیش از ارسال آن، تأیید کنید که دیسک صرفاً پر یا به شدت تکهتکه (fragmented) نشده باشد و مطمئن شوید که در حین تست، هیچ فرآیندی روی سرور در حال نوشتن سنگین روی دیسک نیست.
این بررسی را در همان روزی که سرور را تحویل میگیرید انجام دهید، نه روزی که احساس میکنید سرعت پایین آمده است؛ تا یک مبنا برای مقایسه در آینده داشته باشید. این کار به طور طبیعی در ده دقیقه اول کار با یک VPS جدید، در کنار تنظیم فایروال و کلیدهای SSH قرار میگیرد. اگر تفاوت بین سطوح مختلف ذخیرهسازی هنوز برایتان مبهم است، آنچه یک SSD VPS واقعاً به شما میدهد مباحث زیربنایی این موضوع را پوشش میدهد.
FAQ
چرا با وجود اینکه میزبان از NVMe استفاده میکند، دستور lsblk نام /dev/vda را نشان میدهد؟
زیرا vda نام درایور virtio-blk در سیستمعامل مهمان (guest) است، نه سختافزار موجود در میزبان. هایپرویزور KVM یک دستگاه بلوک پارا-مجازی (paravirtual) ارائه میدهد که توسط یک فایل، logical volume یا dataset پشتیبانی میشود؛ این فضای ذخیرهسازی پشتیبان میتواند روی درایوهای NVMe قرار داشته باشد بدون آنکه سیستمعامل مهمان از آن آگاه شود. این نام تنها لایه مجازیسازی را توصیف میکند. تنها اندازهگیری تأخیر (latency) است که نوع رسانه را مشخص میکند.
آیا مقدار 0 برای rotational ثابت میکند که من دیسک NVMe دارم؟
خیر. مقدار /sys/block/<dev>/queue/rotational که حاوی 0 است، صرفاً به این معناست که هسته (kernel) تشخیص داده دستگاه دارای صفحات چرخان نیست. در virtio، این مقدار توسط یک بیت ویژگی (feature bit) تعیین میشود که میزبان آن را انتخاب میکند. این مقدار فقط وجود هارد دیسکهای معمولی را رد میکند. این گزینه نمیتواند تفاوت بین NVMe و SATA SSD را تشخیص دهد و همچنین نمیتواند تفاوت بین حافظه فلش محلی و یک volume تحت شبکه را مشخص کند. با این حال، مقدار 1 همچنان قابل بررسی است، زیرا با هر طرحی که به عنوان حافظه solid state فروخته میشود، در تضاد است.
چرا دستور nvme list در VPS من خالی است؟
زیرا هیچ کنترلر NVMe به سیستمعامل مهمان شما ارائه نشده است. دستورات nvme list و lspci هر دو آنچه را که ماشین مجازی میبیند میخوانند و یک دیسک virtio-blk یا virtio-scsi هیچ کنترلر NVMe برای فهرستبندی ارائه نمیدهد. یک جدول خالی در اکثر طرحهای VPS نتیجهای طبیعی است و اثباتکننده این نیست که میزبان درایوهای NVMe ندارد. ابزار nvme-cli را با sudo apt install -y nvme-cli نصب کنید و انتظار جدول خالی را داشته باشید، مگر آنکه یک کنترلر به صورت مستقیم (passthrough) به ماشین شما متصل شده باشد.
چه نتیجهای در fio نشاندهنده ذخیرهسازی در کلاس NVMe است؟
در عمق صف (queue depth) 1 با خواندن تصادفی 4k و --direct=1، میانگین تأخیر تکمیل عملیات در حدود 110 میکروثانیه در کلاس NVMe قرار دارد و تقریباً 9,000 IOPS از آن حاصل میشود. مقدار حدود 320 میکروثانیه نشاندهنده یک SATA SSD و مقدار حدود 900 میکروثانیه نشاندهنده ذخیرهسازی متصل به شبکه (NAS) است که در آن هر عملیات خواندن از یک گام شبکه عبور میکند. اینها بازههای معمول منتشر شده برای اوت 2026 هستند؛ بنابراین به جای ارقام دقیق، مرتبه بزرگی (orders of magnitude) را مقایسه کنید و پیش از نتیجهگیری، تست را در ساعات مختلف تکرار کنید.