В настоящее время я экспериментирую с различными способами повышения скорости записи в довольно большой вращающийся дисковый массив программного рейда (mdadm) в Debian с использованием быстрых устройств NVMe.
я нашел что использование пары таких устройств (raid1, зеркальное отображение) для хранения журнала файловой системы дает интересные преимущества в производительности. Для этого я использую следующие варианты крепления: noatime,journal_aync_commit,data=journal
.
В своих тестах я также обнаружил, что добавление barrier=0
вариант предлагает значительные преимущества с точки зрения производительности записи. Однако я не уверен, что этот параметр безопасен для использования в моей конкретной конфигурации файловой системы. Это то, что ядро документация говорит о барьерах записи ext4:
Барьеры записи обеспечивают надлежащий порядок журнальных коммитов на диске, что делает использование кэшей записи на энергозависимый диск безопасным при некотором снижении производительности. Если ваши диски так или иначе имеют резервное питание от батареи, отключение барьеров может безопасно повысить производительность.
Я использую конкретное устройство NVMe. Intel DC P3700 который имеет встроенную защиту от потери питания, что означает, что в случае неожиданного отключения любые данные, все еще присутствующие во временных буферах, безопасно передаются в хранилище NAND благодаря резервному хранилищу энергии.
Итак, мой вопрос: могу ли я безопасно отключить барьеры записи ext4, если журнал хранится на устройстве с кешем с резервным питанием от аккумулятора, а остальная часть самой файловой системы находится на дисках, на которых нет этой функции?
Я пишу новый ответ, потому что после дальнейшего анализа я не думаю, что предыдущий ответ правильно.
Если мы посмотрим на write_dirty_buffers
функция, он выдает запрос на запись с REQ_SYNC
флаг, но он не вызывает сброса кеша или барьера. Это достигается blkdev_issue_flush
вызов, который соответствующим образом стробируется проверкой JDB2_BARRIER
флаг, который сам присутствует только когда файловая система смонтирована с включенными барьерами.
Итак, если мы оглянемся на checkpoint.c
барьеры имеют значение только тогда, когда транзакция удаляется из журнала. В Комментарии в коде являются здесь информативными, говоря нам, что этот барьер записи вряд ли понадобится, но все же существует в качестве меры предосторожности. Я думаю, здесь предполагается, что к тому времени, когда транзакция будет удалена из журнала, сами данные вряд ли все еще будут оставаться в кеше диска и еще не сохранены в постоянном хранилище. Но поскольку это всего лишь предположение, барьер записи все равно срабатывает.
Так почему же не используются барьеры при записи данных в основную файловую систему? Я думаю, что ключ здесь в том, что, пока журнал согласован, метаданные, отсутствующие в файловой системе (например, потому что они были потеряны в случае потери питания), обычно восстановлено во время просмотра журнала, таким образом избегая повреждения файловой системы. Кроме того, использование data=journal
должен также гарантировать согласованность фактических данных файловой системы, потому что, насколько я понимаю, процесс восстановления также будет записывать блоки данных, которые были зафиксированы в журнале как часть его механизма воспроизведения.
Таким образом, хотя ext4 на самом деле не очищает дисковые кеши в конце контрольной точки, следует предпринять некоторые шаги, чтобы максимизировать возможность восстановления в случае потери питания:
Файловая система должна быть смонтирована с помощью data=journal
, и нет data=writeback
(data=ordered
недоступен при использовании внешнего журнала). Это должно быть очевидно: нам нужны копии всех блоков входящих данных внутри журнала, поскольку именно они могут быть потеряны в случае отключения питания. Это не дорого с точки зрения производительности, поскольку устройства NVMe очень быстрые.
Следует использовать максимальный размер журнала в 102400 блоков (400 МБ при использовании блоков файловой системы 4K), чтобы максимально увеличить объем данных, которые можно восстановить при воспроизведении журнала. Это не должно быть проблемой, поскольку все устройства NVMe всегда имеют размер не менее нескольких гигабайт.
Проблемы могут возникнуть в случае неожиданного завершения работы во время операции с интенсивной записью. Если транзакции сбрасываются с устройства журнала быстрее, чем диски данных могут очищать свои кеши самостоятельно, может произойти безвозвратная потеря данных или повреждение файловой системы.
Таким образом, на мой взгляд, суть в том, что отключение барьеров записи не на 100% безопасно, хотя можно принять некоторые меры предосторожности (№1 и №2), чтобы сделать эту настройку немного безопаснее.
Другой способ задать свой вопрос: при выполнении контрольной точки, то есть при записи данных в журнале в фактическую файловую систему, ext4 очищает кеш (вращающихся дисков, в вашем случае) перед тем, как пометить транзакцию как завершенную и обновлять журнал соответствующим образом?
Если мы посмотрим на исходный код jbd2 (который отвечает за ведение журнала) в checkpoint.c Мы видим, что jbd2_log_do_checkpoint()
звонит в конец:
__flush_batch(journal, &batch_count);
который звонки:
write_dirty_buffer(journal->j_chkpt_bhs[i], REQ_SYNC);
Так что, похоже, это должно быть безопасно.
По теме: в прошлое также был предложен патч для использования WRITE_SYNC в контрольной точке журнала: причина заключалась в том, что запись буферов имела слишком низкий приоритет и вызывала заполнение журнала в ожидании завершения записи
Если отключение барьеров записи значительно повышает производительность, это означает, что вам не следует отключать барьеры записи и ваши данные находятся под угрозой. См. Пояснения в этой части FAQ XFS.