RE:NODE

Ресурсы11 мин чтения

Что NVMe действительно меняет, а что нет

NVMe - это не более быстрый сервер, а меньшая задержка на мелких записях. Какие операции он меняет - сохранения, перезапуски, backup, коммиты базы - и каких не касается никогда.

Обновлено

0 прочтений

NVMe встречается в каждом сравнении хостингов и почти никогда не объясняется, из-за чего он стал означать «быстро» так же расплывчато, как «премиальное оборудование». Это не более быстрый сервер. Это протокол хранения с примерно десятой долей задержки на запрос по сравнению с SSD на SATA и очередями, рассчитанными на параллелизм, и он важен ровно настолько, насколько ваша нагрузка обращается к диску. Для шутера, упирающегося в CPU, это почти ноль. Для базы данных, коммитящей транзакции, или большого мира, записывающего сохранение каждые десять минут, или архива backup на 40 ГБ это разница между подтормаживанием, которого никто не замечает, и таким, которое стоит вам игроков. Эта статья о том, как отличить эти случаи.

Что такое NVMe на самом деле#

Путаница возникает оттого, что сравнивают не то. NVMe - это не тип флеш-памяти; микросхемы в диске NVMe и в SSD на SATA - одно и то же. Различие в том, как компьютер с ними разговаривает.

SSD на SATA использует AHCI - протокол, разработанный в 2004 году для механических дисков. В AHCI одна очередь команд глубиной 32, и он исходит из того, что дорогая часть запроса - это перемещение физического рычага. Канал SATA III на практике упирается примерно в 550 МБ/с.

NVMe спроектирован для флеш-памяти и подключается прямо к PCIe. Он поддерживает до 65 535 очередей по 65 536 команд, что кажется абсурдом, пока не вспомнишь, что флеш внутренне параллелен по десяткам микросхем, а AHCI никогда не мог загрузить их все. Диск PCIe 3.0 x4 даёт примерно 3 500 МБ/с; диск PCIe 4.0 x4 - примерно 7 000 МБ/с.

HDD 7200 об/минSSD SATANVMe (PCIe 3.0)
Последовательное чтение150-200 МБ/с~550 МБ/с~3 500 МБ/с
IOPS случайного чтения 4K100-20080 000-100 000300 000-1 000 000
Типичная задержка запроса5-10 мс100-200 мкс20-100 мкс
Глубина очереди132практически неограниченна

Строка про пропускную способность - та, которую цитирует маркетинг, и та, что важна меньше всего. Почти ничто из того, что делает игровой сервер, не является последовательным чтением на 3 ГБ. Важны последние две строки: сколько занимает один мелкий запрос и сколько их может выполняться одновременно. Именно там лежит разница на порядок, и поэтому нагрузка из тысяч мелких чтений и записей - а именно такие сохранение мира и коммит базы - ведёт себя совершенно иначе.

Хранилище - это ещё и не только диск. RE:NODE использует NVMe повсюду, на пуле ZFS, а такая файловая система, как ZFS, добавляет своё поведение: каждый блок получает контрольную сумму, так что скрытое повреждение обнаруживается, а не отдаётся; запись работает по принципу copy-on-write, так что при потере питания остаётся целостная файловая система, а не наполовину записанная; а кэш чтения в RAM означает, что горячий рабочий набор часто вообще не доходит до диска. Диск задаёт нижнюю границу; файловая система решает, как часто вы о неё ударяетесь.

Где игровой сервер обращается к диску#

В большем числе мест, чем принято думать, и всплесками, а не непрерывно.

сериализация мирабуферизуетсяпри flush или fsyncблокировка до конца, если синхронноИгровой серверглавный потоквызов write()возвращается быстроPage cacheв RAMФайловая системаZFS, ext4Устройство NVMeсам сброс на диск
Путь записи одного сохранения мира

Работа с диском на игровом сервере делится на семь задач с очень разными профилями:

  • Сохранения мира. Периодические, и обычно хотя бы частично в главном потоке. Minecraft записывает изменённые чанки в файлы регионов (region/r.0.0.mca, каждый содержит блок чанков 32x32); Valheim записывает один файл .db на весь мир; Palworld и survival-игры на Unreal записывают большие блобы сохранений. Сохранение большого мира - это тысячи мелких записей или одна огромная, и то и другое упирается в диск.
  • Загрузка чанков и зон. Игрок, заходящий на неисследованную территорию, вызывает чтение с диска либо генерацию и последующую запись. Именно это даёт подтормаживание, когда кто-то летит через карту.
  • Журналы. Непрерывные, мелкие, только дозапись. Дёшево, пока какой-нибудь плагин не начнёт логировать каждую постановку блока.
  • Базы данных плагинов и модов. Файлы пользователей EssentialsX, журнал блоков CoreProtect, файл SQLite, который долбит каждое действие на сервере. Тихо это самая тяжёлая дисковая нагрузка на многих серверах Minecraft.
  • Запуск. Чтение jar или бинарников игры, списка модов, плагинов и стартовых чанков. Серверу с модами приходится прочитать несколько гигабайт, прежде чем он примет подключение.
  • Backup. Чтение всего мира и запись сжатого архива. Почти чистая работа с диском.
  • Обновления и загрузки из Workshop. Большие последовательные записи плюс проверочные чтения.

Где NVMe заметен, по порядку#

ОперацияЧто этоЧто меняет NVMe
Периодическое сохранение мираТысячи мелких записейЗамирание становится короче, порой невидимым
Backup и восстановлениеПрочитать всё, записать архивМинуты превращаются в малую их долю
Запуск сервераБольшие последовательные и случайные чтенияЗаметно быстрее на серверах с модами
Загрузка чанков при исследованииМелкие случайные чтенияМеньше подтормаживаний при движении игроков
Коммит базы данныхfsync на каждую транзакциюСамая большая разница из всех
Записи SQLite плагиновПостоянные мелкие синхронные записиУбирает распространённую скрытую стоимость тика
Записи журналаМелкие дозаписиНичего заметного

Случай с сохранением заслуживает подробностей, потому что именно его игроки чувствуют. Большинство игр сериализуют мир и записывают его, пока симуляция ждёт. На мире, выросшем до десятков гигабайт, эта запись - самый долгий одиночный блок цикла тика, и она происходит по таймеру, вечно. Valheim - чистый пример: весь мир - один файл, записываемый каждые -saveinterval секунд, и на зрелом мире пауза измерима. Сокращение интервала уменьшает то, что можно потерять при сбое, и увеличивает частоту, с которой вы платите паузой, а быстрое хранилище делает этот обмен дешёвым. Настройки сохранения разобраны в руководстве по Valheim.

Backup - вторая честная победа, и это почти чистая работа с диском. Ночное задание, читающее мир на 30 ГБ и записывающее сжатый архив, делает ровно ту работу, на которую рассчитано хранилище. На медленных дисках это задание пересекается с вечером, конкурирует с игрой и превращается в загадочный лаг, в котором все обвиняют хостера. На NVMe оно заканчивается, прежде чем кто-то заметит. Оно меняет и то число, которое действительно важно в аварии: не сколько шёл backup, а сколько занимает восстановление; см. резервные копии, которые действительно восстанавливаются и проверка восстановления до того, как оно понадобится.

Где он не меняет ничего#

Эту часть страницы хостингов опускают.

Tick rate на сервере, упирающемся в CPU. Если симуляция не может завершить шаг в отведённый бюджет, потому что симулировать слишком много, диск в этом не участвовал. Более быстрое хранилище ничего не меняет, а деньги лучше было бы потратить на тактовую частоту. Как понять, что у вас, помогает статья CPU или RAM.

Сетевая задержка. Игрок с 180 мс находится в 180 мс от сервера. У хранилища на это нет мнения.

Всё, что уже в памяти. Активный мир, список сущностей, состояние плагинов, куча JVM: между сохранениями ничто из этого не обращается к диску. Сервер с памятью, достаточной для его рабочего набора, читает с диска редко, и именно поэтому добавление памяти иногда исправляет то, что выглядит как проблема хранилища.

Установившаяся производительность небольшого сервера. Сервер Counter-Strike на статичной карте читает карту один раз и остаток вечера практически не выполняет дискового ввода-вывода. Хранилище в таком тарифе - просто место, где лежат файлы.

Плохая конфигурация. Плагин, делающий синхронный запрос к базе в главном потоке на каждом тике, медленный и на NVMe. Просто медленный чуть быстрее.

Базы данных - там, где он действительно доминирует#

Если вы запускаете базу данных - экземпляр Postgres или MongoDB, сервер FiveM с настоящим хранилищем, экономический плагин Minecraft с тысячами транзакций - задержка хранилища задаёт жёсткий потолок пропускной способности, а арифметика безжалостна.

Надёжная база вызывает fsync, прежде чем подтвердить коммит, потому что коммит, который есть только в page cache, - это обещание, которое она не выдержит при потере питания. Этот fsync - синхронный круговой путь до устройства, и одно соединение не может коммитить быстрее, чем по одному fsync за раз:

code
max commits per second, per connection = 1 / fsync latencyHDD,  8 ms fsync   ->    125 commits/sSATA, 1 ms fsync   ->  1,000 commits/sNVMe, 50 us fsync  -> 20,000 commits/s

Это потолки, а не прогнозы, и реальные системы группируют коммиты от нескольких соединений и достигают большего. Но именно такая форма объясняет, почему приложение с интенсивной записью на медленном хранилище упирается в стену, которую не убирает никакая настройка запросов, и почему то же приложение на NVMe просто ничего не замечает. Настройки, связанные с этим, описаны в статье настройка PostgreSQL для небольших серверов, а вторая половина - сами запросы - в статье explain analyze для медленных запросов.

Производительность чтения важна иначе. Запрос, находящий данные в кэше, вообще не касается диска - потому shared_buffers и page cache операционной системы настраивают первыми. NVMe меняет то, что происходит при промахе кэша, а на рабочем наборе, превышающем память, это происходит большую часть времени. Тарифы хостинга баз данных рассчитаны с учётом этого, но общее правило верно везде: память убирает чтения, а быстрое хранилище делает дешёвыми те чтения, которые убрать нельзя.

Как измерить самостоятельно#

Не верьте листу спецификации и особенно не верьте dd.

bash
# Misleading: writes through the page cache, measures RAM$ dd if=/dev/zero of=test bs=1M count=1024# Better, but still only sequential throughput$ dd if=/dev/zero of=test bs=1M count=1024 oflag=direct conv=fdatasync

Последовательная пропускная способность - наименее значимое число. Вам нужны задержка и IOPS мелкого случайного ввода-вывода:

bash
$ fio --name=randread --ioengine=libaio --direct=1 --rw=randread \    --bs=4k --iodepth=32 --numjobs=1 --size=1G --runtime=30 \    --time_based --group_reporting$ fio --name=syncwrite --ioengine=sync --fsync=1 --rw=write \    --bs=4k --size=256M --runtime=30 --time_based

Первый даёт IOPS случайного чтения и распределение задержек. Второй - тест fsync, и именно он предсказывает поведение базы данных. Читайте 99-й процентиль задержки, а не среднее: среднее говорит, как обычно себя ощущается, а хвост - как выглядит замирание.

Для быстрой проверки без установки чего-либо ioping -c 20 . печатает задержку по запросам в текущем каталоге. Для наблюдения за работающим сервером:

bash
$ iostat -xz 1

Смотрите r_await и w_await - среднее число миллисекунд ожидания запроса - и aqu-sz, среднюю глубину очереди. Игнорируйте %util на устройстве NVMe: он создавался для дисков с одной очередью и показывает 100 % на диске, который почти не работает, потому что измеряет, был ли в полёте хоть один запрос, а не насыщено ли устройство. Высокий %util при w_await 0,1 мс - это здоровый диск NVMe, а не узкое место.

На хостинге с панелью у вас не будет fio, а полезная замена - график диска рядом с графиками памяти и CPU. Пилообразный график диска, точно совпадающий с подтормаживаниями, о которых сообщают игроки, - это ваш ответ, а формы графиков разобраны в статье как читать график нагрузки сервера.

Место на диске - отдельный вопрос от скорости диска#

В тарифах указан размер диска, и все читают это как объём хранилища, каким оно и является, но это число влияет на производительность двумя способами, о которых стоит знать.

Работа почти на полном диске медленна. Флешу нужны свободные блоки для записи, и почти полный диск тратит время на перетасовку данных, чтобы освободить место. Файловым системам с copy-on-write, включая ZFS, для эффективной работы нужно свободное место. Держать заполнение ниже примерно 80 % - это настройка производительности, а не просто аккуратность.

Backup лежат в том же месте, если только не лежат отдельно. Встроенная функция резервного копирования игры пишет рядом с миром, а значит, мир на 30 ГБ с четырьмя хранимыми копиями требует 150 ГБ и защищает ровно от одного вида сбоя: повреждённого сохранения. Она ничего не делает против удалённого сервера или неудачного восстановления. Платформенные backup на RE:NODE копируются на отдельное оборудование, проверяются и по расписанию чистятся, а слоты резервных копий в панели хранятся вне машины, которую они защищают, - именно это свойство делает backup резервной копией, а не второй копией файла на том же диске.

Отсюда совет по выбору размера: выбирайте диск по миру, который ожидаете через год, плюс место для архивов, а не по тому, каков мир сегодня. Миры только растут, а предварительная генерация ограниченного мира - единственный приём, делающий этот рост предсказуемым.

FAQ#

Стоит ли переплачивать за NVMe?

Если это отдельная строка в счёте, сначала посмотрите на свою нагрузку. Он стоит своих денег для баз данных, для больших миров, которые часто сохраняются, и для всего, где часто делают backup. Он не стоит наценки для небольшого шутера или бота Discord, которые после запуска почти не трогают диск. На RE:NODE это не отдельная строка: каждый тариф на NVMe, включая самый дешёвый, потому что альтернатива - ложная экономия на оборудовании, составляющем малую часть затрат.

Исправит ли NVMe лаг моего сервера?

Только если лаг периодический и совпадает с сохранениями, backup или исследованием мира игроками. Лаг, который постоянен, растёт с числом сущностей и проявляется как высокое время тика при спокойном графике диска, - это проблема CPU, и хранилище её не тронет.

Ускорит ли NVMe запуск моего сервера?

Да, заметно, на всём с большим миром или длинным списком модов: такой запуск - это в основном чтение файлов. Ванильный сервер с маленьким миром стартует за несколько секунд на чём угодно, так что там разница не видна.

В чём разница между NVMe и SSD?

SSD - это флеш-хранилище; NVMe - протокол для работы с ним по PCIe. Большинство «SSD» в рекламе хостингов - это SSD на SATA с AHCI, протоколом 2004 года с одной неглубокой очередью. Те же микросхемы, но очень разные задержка и параллелизм.

Нужен ли NVMe для сервера Minecraft?

Он помогает больше, чем принято думать, потому что дисковая работа Minecraft - это мелкие случайные чтения и записи: загрузка чанков при исследовании, файлы регионов при сохранении и базы плагинов вроде CoreProtect, пишущие постоянно. Всё это не пропускная способность, а задержка, а именно её NVMe и меняет.

Может ли медленное хранилище вызывать низкий TPS?

Да, косвенно и с перебоями. Сохранение или синхронная запись плагина, блокирующие главный поток, тратят бюджет тика, что проявляется огромным максимальным временем тика при нормальном среднем. Этот узор - проблема хранилища, маскирующаяся под проблему CPU, а как отличить одно от другого, описано в статье что на самом деле означает tick rate.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000