هل قرص VPS لديك NVMe فعلًا؟ تحقّق من Linux
يقول مضيفك إن القرص NVMe؟ افحصه من داخل الضيف باستخدام lsblk وsysfs وnvme-cli، ثم شغّل اختبار fio محدوداً، وافهم كيف يخفي virtio القرص الحقيقي.
تحقّق من قرص NVMe على Linux في أربع خطوات
للتحقّق من قرص NVMe على VPS يعمل بنظام Linux، نفّذ أربعة فحوص بالترتيب: lsblk لمعرفة اسم الجهاز، والعلامة rotational في sysfs للتحقّق من الوسائط الدوّارة، وnvme list للتحقّق من وجود وحدة تحكم NVMe فعلية، ثم شغّل fio لفترة قصيرة للتحقّق من الرقم الوحيد الذي لا يستطيع المضيف تزييفه. تستغرق الفحوص الثلاثة الأولى ثانية واحدة لكل فحص. أما الفحص الأخير فيحسم المسألة، لأن hypervisor يخفي القرص الفعلي عن النظام الضيف في معظم منصات VPS.
NVMe (non-volatile memory express) هو البروتوكول الذي تستخدمه وحدات التخزين الفلاشية عبر مسارات PCIe (peripheral component interconnect express). وقد حلّ محل مسار SATA وAHCI المصمم لمحركات الأقراص الدوّارة. وهو سريع لأنه يزيل عنق زجاجة في قوائم الانتظار بين CPU ووحدة التخزين الفلاشية. داخل آلة افتراضية، نادراً ما تتعامل مباشرة مع هذا البروتوكول. بل تتعامل مع قرص افتراضي يجهّزه المضيف لك، ولذلك يصف اسم الجهاز في النظام الضيف برنامج تشغيل، لا الوسيط التخزيني الموجود في الرف.
الخطوة 1: ماذا يعرض lsblk؟
يقرأ lsblk قائمة أجهزة الكتل من النواة. يخفي الخيار -d الأقسام، لذلك ترى سطراً واحداً لكل قرص.
lsblk -d -o NAME,ROTA,SIZE,TYPE,TRAN,MODELعادةً ما يستجيب KVM VPS كما يلي:
NAME ROTA SIZE TYPE TRAN MODEL
vda 0 80G diskتغطي أنماط التسمية الثلاثة هذه كل خادم Linux تقريباً:
- يشير
nvme0n1إلى مساحة الأسماء 1 على وحدة تحكم NVMe رقم 0. يستخدم الضيف جهاز NVMe، حقيقياً أو محاكياً. - يشير
sdaإلى طبقة SCSI. تظهر أقراص SATA وSAS الحقيقية هنا، وكذلك برنامج التشغيل virtio-scsi. - يشير
vdaإلى virtio-blk، وهو برنامج تشغيل الكتل شبه الافتراضي الذي تستخدمه معظم مضيفات KVM افتراضياً.
يعرض العمود TRAN (النقل) القيمة nvme لجهاز NVMe، والقيمة sata لقرص SATA يستطيع الضيف رؤيته مباشرة. يكون هذا العمود فارغاً عادةً مع virtio-blk، لأن الضيف لا يملك وسيلة نقل فعلية يمكنه الإبلاغ عنها. يكون MODEL فارغاً للسبب نفسه. تُعد سلسلة الطراز الفارغة في 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 عندما يعتقد kernel أن الجهاز يضم أطباقاً دوّارة، وعلى 0 في الحالات الأخرى. في الأجهزة الفعلية، تأتي القيمة من وحدة التخزين. أما مع virtio-blk، فتأتي من بتّ ميزة يحدده المضيف، لذلك تستبعد قيمة 0 وجود قرص صلب عادي، لكنها لا تثبت شيئاً أكثر من ذلك. اقرأها على أي حال: وجود 1 في خطة تُباع على أنها تخزين solid state تناقض واضح، وهي لقطة الشاشة التي لا يستطيع فريق الدعم الاعتراض عليها.
يحل readlink -f الرابط الرمزي في sysfs ويطبع الناقل الذي يتصل به الجهاز:
/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، لكنها مأخوذة من kernel بدلاً من عمود منسّق، وهذا مفيد عندما يكون الحقل 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 صفاً واحداً لكل مساحة أسماء، ويتضمن الرقم التسلسلي لوحدة التحكم، وسلسلة الطراز، ومراجعة البرنامج الثابت. يعني الجدول الفارغ عدم إتاحة أي جهاز NVMe للآلة الضيفة. ويعني عدم طباعة lspci لأي سطر مطابق الشيء نفسه من الجانب الآخر: لا يحتوي ناقل PCI الافتراضي الذي تستطيع الآلة الضيفة رؤيته على وحدة تحكم NVMe. هاتان النتيجتان الفارغتان هما النتيجة المعتادة على VPS يستخدم virtio، ولا تشكّل أي منهما دليلاً على عدم احتواء المضيف على أقراص NVMe.
إذا ظهرت مساحة أسماء، فإن nvme-cli يقدّم معلومات إضافية. يطبع sudo nvme id-ctrl /dev/nvme0 هوية وحدة التحكم، بينما يطبع sudo nvme smart-log /dev/nvme0n1 درجة الحرارة، وساعات التشغيل منذ تشغيل الطاقة، والنسبة المئوية من قدرة التحمل المقدّرة للكتابة التي استُخدمت. شغّل هذين الأمرين فقط عندما يسرد nvme list جهازاً فعلياً، لأن كلا الأمرين يحتاج إلى فتح عقدة /dev/nvme* حقيقية.
لماذا يعرض خادم NVMe فعلياً /dev/vda
يحدّد برنامج Hypervisor نموذج الجهاز الذي يراه الضيف، ولا يعتمد هذا الاختيار على وسيط التخزين الأساسي. توجد 3 ترتيبات شائعة.
- استخدام virtio-blk أو virtio-scsi فوق ملف، أو وحدة تخزين منطقية، أو مجموعة بيانات ZFS موجودة على محركات NVMe. سترى
vdaأوsda. التخزين من نوع NVMe، لكن لا يمكن للضيف معرفة ذلك. - استخدام وحدة تحكم NVMe محاكاة أمام أي نوع من التخزين. سترى
nvme0n1حتى عندما تُخزَّن البيانات على مصفوفة SATA أو على وحدة تخزين شبكية تبعد رفَّين. - استخدام PCIe passthrough، حيث يمرّر المضيف وحدة تحكم فعلية إلى ضيف واحد. سترى
nvme0n1حقيقياً مع سلسلة طراز فعلية. هذا نادر في خطط VPS المشتركة، لأن البطاقة تصبح مخصصة لذلك العميل وحده.
لذلك قد يضللك اسم الجهاز في كلا الاتجاهين. والأسوأ أن المضيف قد يضع ذاكرة تخزين مؤقتة من نوع write-back، أو طبقة RAID، أو وحدة تخزين شبكية مكررة بين عمليات الكتابة التي تجريها ووحدات الفلاش. يغيّر كل عنصر من هذه العناصر الأداء الذي تحصل عليه من دون تغيير أي اسم في /sys. لهذا السبب يبدأ الفحص من الاسم، لكنه لا ينتهي عنده. إذا كنت لا تزال تختار خطة، توضّح الفروق بين تخزين NVMe وتخزين SATA SSD ما الذي تستحق كل فئة أن تدفع مقابله فعلياً.
الاختبار الصادق هو زمن الاستجابة، لذا قِسه
يُجري fio (أداة اختبار الإدخال والإخراج المرنة) عمليات قراءة فعلية من ملف فعلي، ويعرض المدة التي استغرقتها كل عملية. تُعد عمليات القراءة العشوائية الصغيرة عبء العمل المناسب هنا، لأنها تكشف زمن الرحلة ذهاباً وإياباً إلى وسيط التخزين، ولا يمكن لخدمة القراءة المسبقة تلبية هذه العمليات.
أنشئ ملف الاختبار أولاً، وتحقق من أن نظام الملفات هذا يقبل الإدخال والإخراج غير المخزَّنين مؤقتاً. يفتح --direct=1 الملف باستخدام O_DIRECT، ما يتجاوز ذاكرة الصفحات المؤقتة. ومن دون ذلك، ستقيس ذاكرة 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جرى تقييد التشغيل عمداً: مهمة واحدة، وعمق قائمة انتظار يساوي 1، ومدة عشرين ثانية، و256 MB من البيانات. لن يملأ ذلك القرص، ولن يؤدي إلى تصنيفك على أنك تسيء الاستخدام. كما أن عمق قائمة الانتظار 1 هو الإعداد الصادق لهذا السؤال، لأن قوائم الانتظار العميقة تتيح لجهاز بطيء الاختباء خلف المعالجة المتوازية، بينما يظل زمن الاستجابة مرتفعاً.
قراءة مخرجات fio
هناك سطران مهمان. يبدو سطر الملخص مثل read: IOPS=9012, BW=35.2MiB/s، ويطبع fio تحته كتلة clat. تمثل clat زمن استجابة الإكمال: الوقت بين إرسال fio لطلب القراءة وتسليم النواة البيانات إليه. اقرأ قيمة avg، ثم اقرأ المئين 99.00th في قائمة clat percentiles. يوضح المتوسط فئة التخزين. ويوضح المئين 99 مدى تكرار اضطرارك إلى الانتظار بسبب جار على المضيف نفسه.
يطبع fio زمن الاستجابة بالميكروثانية عندما تكون القيم صغيرة، وينتقل إلى الملي ثانية عندما لا تكون كذلك. تحقق من الوحدة في السطر السابق قبل مقارنة أي شيء.
ما الأرقام التي تفصل فئة NVMe عن فئة SATA
القيم أدناه هي قيم منشورة نموذجية لقراءات عشوائية مفردة بحجم 4k عند عمق قائمة انتظار 1، وقد جُمعت من وثائق المورّدين واختبارات الأداء التي أجراها المجتمع حتى August 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"
}
]يستجيب مجلد NVMe محلي لقراءة عشوائية واحدة بحجم 4k خلال نحو 110 ميكروثانية، ويصل إلى نحو 9,000 IOPS عند عمق قائمة انتظار 1. ويبلغ زمن استجابة SSD SATA المحلي نحو 320 ميكروثانية، ويحقق 3,100 IOPS. أما التخزين الكتلي المتصل عبر الشبكة فيبلغ نحو 900 ميكروثانية و1,100 IOPS، لأن كل قراءة مفردة تمر عبر قفزة شبكية قبل الوصول إلى أي ذاكرة فلاش.
عند عمق قائمة انتظار 1، يعبّر العمودان عن الحقيقة نفسها بصيغتين: قراءة واحدة في كل مرة تعني أن معدل النقل يساوي ببساطة مقلوب زمن الاستجابة. إذا كان متوسطك أقرب إلى 110 منه إلى 320 ميكروثانية، فأنت تستخدم وحدة تخزين من فئة NVMe، بغض النظر عمّا قرر lsblk تسميته. وإذا كان أقرب إلى 900 ميكروثانية، فهناك مكوّن أبطأ من فلاش محلي في المسار، وكلمة NVMe في صفحة الطلب تصف أقراص المضيف، لا مجلدك.
شغّل الاختبار أكثر من مرة قبل تقديم شكوى
الاختبار الواحد عينة، وليس نتيجة. يشترك VPS في أقراصه مع عملاء آخرين، لذلك قد يضاعف جار نشط زمن الاستجابة لمدة عشر دقائق ثم يختفي تأثيره. تمنح بعض المنصات أيضاً أرصدة burst، ما يجعل الدقائق الأولى من أي اختبار تبدو ممتازة. شغّل الأمر نفسه ثلاث أو أربع مرات في ساعات مختلفة من اليوم، وقارن أسوأ نتيجة لا أفضل نتيجة. النتيجة السيئة الواحدة حالة عابرة. أما النمط المتكرر فهو خلل يستحق فتح تذكرة دعم، وستكون التذكرة أكثر فاعلية عند إرفاق ثلاثة مخرجات مؤرخة من fio. وللحصول على صورة أشمل تشمل CPU والشبكة إضافة إلى القرص، يستخدم اختبار VPS شامل الانضباط نفسه مع الأنظمة الفرعية الأخرى.
ماذا تفعل بالنتيجة
إذا كان زمن الاستجابة ضمن نطاق NVMe، فتوقف عن القلق بشأن اسم الجهاز وانتقل إلى الخطوة التالية. vda ليس تراجعاً في الأداء. فهو أسرع برنامج تشغيل للقرص الافتراضي توفره معظم المضيفات، وهو الخيار المطلوب هنا.
إذا كان زمن الاستجابة ضمن نطاق التخزين الشبكي، مع أن الخطة تُباع على أنها NVMe محلي، فلديك ادعاء محدد وقابل لإعادة الإنتاج: أمر fio الدقيق، ومتوسط زمن إكمال العمليات، والأوقات التي شغّلت فيها الاختبار. هذه حالة مناسبة لفتح تذكرة دعم، وليست جدالاً في المنتدى. قبل إرسالها، تأكد من أن القرص ليس ممتلئاً أو شديد التجزئة، وتأكد من عدم وجود عملية على الخادم تكتب بكثافة أثناء الاختبار.
شغّل هذا الفحص في يوم تهيئة الخادم، لا في اليوم الذي تشعر فيه بأن شيئاً ما أصبح بطيئاً، حتى يتوفر لديك خط أساس تقارن به لاحقاً. ويناسب ذلك طبيعياً الدقائق العشر الأولى على VPS جديد، إلى جانب إعداد جدار الحماية ومفاتيح SSH. إذا كان الفرق بين مستويات التخزين لا يزال غير واضح، فتشرح ما الذي يوفّره VPS مزود بقرص SSD فعلياً الأساس الذي يعتمد عليه هذا الموضوع.
FAQ
لماذا يعرض lsblk /dev/vda بينما يعلن مضيفي عن NVMe؟
لأن vda يسمّي برنامج تشغيل virtio-blk في الضيف، وليس العتاد الموجود على المضيف. يقدّم مشرف KVM جهاز كتل افتراضياً شبه مباشر مدعوماً بملف أو وحدة تخزين منطقية أو مجموعة بيانات، وقد يكون مخزن الدعم هذا موجوداً على محركات NVMe من دون أن يعرف الضيف ذلك. يصف الاسم طبقة المحاكاة الافتراضية. ولا يصف وسيط التخزين إلا قياس زمن الاستجابة.
هل تثبت قيمة rotational 0 أن لدي قرص NVMe؟
لا. يعني احتواء /sys/block/<dev>/queue/rotational على 0 أن النواة لا تعتبر الجهاز مزوداً بأطباق دوارة، وتُضبط هذه القيمة في virtio بواسطة بت ميزة يختاره المضيف. وهي تستبعد القرص الصلب العادي. لكنها لا تميّز بين NVMe وSATA SSD، ولا تميّز بين ذاكرة فلاش محلية ووحدة تخزين عبر الشبكة. تظل قيمة 1 جديرة بالمعالجة، لأنها تتعارض مع أي خطة تُباع على أنها تخزين من الحالة الصلبة.
لماذا تكون قائمة nvme فارغة على VPS لدي؟
لأنه لا توجد وحدة تحكم NVMe مكشوفة للضيف. يقرأ كل من nvme list وlspci ما تستطيع الآلة الافتراضية رؤيته، ولا يقدّم قرص virtio-blk أو virtio-scsi أي وحدة تحكم NVMe لإدراجها. والجدول الفارغ هو النتيجة المعتادة في معظم خطط VPS، ولا يثبت أن المضيف يفتقر إلى محركات NVMe. ثبّت nvme-cli باستخدام sudo apt install -y nvme-cli، وتوقّع بقاء الجدول فارغاً ما لم تُمرَّر وحدة تحكم إلى الضيف.
ما نتيجة fio التي تُعد تخزيناً من فئة NVMe؟
عند عمق طابور يبلغ 1، ومع قراءات عشوائية بحجم 4k و--direct=1، يُعد متوسط زمن الإكمال القريب من 110 ميكروثانية من فئة NVMe، وينتج عنه نحو 9,000 IOPS. وتشير قيمة تقارب 320 ميكروثانية إلى SATA SSD، بينما تشير قيمة تقارب 900 ميكروثانية إلى تخزين متصل بالشبكة، حيث تعبر كل قراءة قفزة شبكية. هذه نطاقات نموذجية منشورة لشهر August 2026، لذا قارن رتب المقدار بدلاً من مقارنة الأرقام الدقيقة، وأعد الاختبار في ساعات مختلفة قبل استخلاص نتيجة.