У меня есть веб-сайт, на котором около 10 миллионов файлов (обложек книг) хранятся в трех уровнях подкаталогов, начиная с [0-f]:
0/0/0/
0/0/1/
...
f/f/f/
Это приводит к примерно 2400 файлам на каталог, что очень быстро, когда нам нужно получить один файл. Более того, это практика, предложенная много вопросов.
Однако, когда мне нужно сделать резервную копию этих файлов, на просмотр каталогов 4k, содержащих 10 млн файлов, уходит много дней.
Поэтому мне интересно, могу ли я хранить эти файлы в контейнере (или в контейнерах 4k), каждый из которых будет действовать точно так же, как файловая система (какой-то смонтированный контейнер ext3 / 4?). Я предполагаю, что это было бы почти так же эффективно, как прямой доступ к файлу в файловой системе, и это было бы большим преимуществом, заключающимся в очень эффективном копировании на другой сервер.
Любые предложения о том, как это сделать лучше всего? Или любая жизнеспособная альтернатива (noSQL, ...)?
Это очень похоже на более простую проблему, с которой сталкиваются серверы новостей USENET и кэширующие веб-прокси: сотни миллионов небольших файлов, к которым осуществляется произвольный доступ. Возможно, вы захотите получить от них подсказку (за исключением того, что им обычно никогда не нужно делать резервные копии).
http://devel.squid-cache.org/coss/coss-notes.txt
Очевидно, что циклический характер файловой системы циклических новостей не имеет отношения к вам, но концепция нижнего уровня, состоящая из нескольких файлов / устройств на диске с упакованными изображениями и быстрого индексации информации, которую пользователь предоставляет для поиска информации о местоположении, очень подходит.
Конечно, это просто аналогичные концепции, о которых говорили люди, о создании файловой системы в файле и монтировании ее через loopback, за исключением того, что вы можете написать свой собственный код файловой системы. Конечно, поскольку вы сказали, что ваша система предназначена в основном для чтения, вы можете выделить раздел диска (или раздел lvm для гибкости в выборе размера) для этой единственной цели. Если вы хотите создать резервную копию, смонтируйте файловую систему в режиме «только для чтения», а затем сделайте копию битов раздела.
Выше я упомянул LVM как полезный компонент, позволяющий динамически изменять размер раздела, чтобы не создавать резервные копии большого количества пустого пространства. Но, конечно, у LVM есть и другие функции, которые могут быть очень применимы. В частности, функция «моментального снимка», которая позволяет вам заморозить файловую систему в определенный момент времени. Любая случайная rm -rf
или что-то еще, что не мешало бы снимку. В зависимости от того, что именно вы пытаетесь сделать, этого может быть достаточно для ваших нужд резервного копирования.
Я уверен, что вы уже знакомы с RAID и, вероятно, уже используете его для обеспечения надежности, но RAID-1 можно использовать и для резервного копирования, по крайней мере, если вы используете программный RAID (вы можете использовать его с аппаратным RAID, но на самом деле это дает более низкую надежность, поскольку для чтения может потребоваться та же модель / версия контроллера). Идея состоит в том, что вы создаете группу RAID-1 с одним диском больше, чем вам действительно нужно, подключенным для вашей нормальной надежности (например, третий диск, если вы используете программный RAID-1 с двумя дисками, или, возможно, большой диск и аппаратное обеспечение). RAID5 с меньшими дисками с программным RAID-1 поверх аппаратного RAID-5). Когда приходит время сделать резервную копию, установить диск, попросить mdadm добавить этот диск в группу raid, подождать, пока он не укажет на полноту, при желании запросить очистку проверки, а затем удалить диск. Конечно, в зависимости от характеристик производительности, вы можете установить диск большую часть времени и извлекать его только для обмена с альтернативным диском, или вы можете установить диск только во время резервного копирования).
Как вы, наверное, знаете, ваша проблема - местность. Типичный поиск по диску занимает около 10 мс. Таким образом, простой вызов stat (или open ()) для 10 миллионов случайно размещенных файлов требует 10 миллионов поисков, или около 100000 секунд, или 30 часов.
Таким образом, вы должны помещать свои файлы в более крупные контейнеры, чтобы релевантным числом была пропускная способность вашего диска (обычно 50-100 МБ / с для одного диска), а не время поиска. Также вы можете использовать RAID-массив, который позволяет увеличить пропускную способность (но не сокращает время поиска).
Я, вероятно, не говорю вам того, чего вы еще не знаете, но я хочу сказать, что ваша идея "контейнера" определенно решит проблему, и подойдет практически любой контейнер. Петлевые крепления, вероятно, будут работать как угодно.
Вы можете смонтировать виртуальную файловую систему с помощью диспетчера loopback, но хотя это ускорит процесс резервного копирования, это может повлиять на нормальные операции.
Другой альтернативой является резервное копирование всего устройства с помощью dd. Например, dd if=/dev/my_device of=/path/to/backup.dd
.
Есть несколько вариантов. Самый простой и должен работать со всеми файловыми системами Linux - это dd
скопировать весь раздел (/dev/sdb3
или /dev/mapper/Data-ImageVol
) в один образ и заархивируйте это изображение. В случае восстановления отдельных файлов, зацикливайте образ (mount -o loop /usr/path/to/file /mountpoint
) и скопируйте нужные файлы. Для полного восстановления раздела вы можете изменить направление исходного dd
, но вам действительно нужен раздел идентичного размера.
Судя по вашему варианту использования, я предполагаю, что восстановление отдельных файлов - очень редкое событие, если оно вообще происходит. Вот почему здесь действительно имеет смысл резервное копирование на основе изображений. Если вам действительно нужно чаще выполнять индивидуальное восстановление, использование поэтапных снимков LVM будет намного удобнее; но вам все равно нужно делать резервные копии на основе образов для тех критических катастроф «мы потеряли все». Восстановление на основе изображений, как правило, много быстрее, чем восстановление на основе tar, просто потому, что оно просто восстанавливает блоки, не требует большого количества операций с метаданными с каждым fopen / fclose, а также может быть очень последовательной дисковой операцией для дальнейшего увеличения скорости.
С другой стороны, как указано в видео Google @casey примерно на полпути, XFS - отличная файловая система (если она сложная). Одна из лучших утилит с XFS - это xfsdump
утилита, которая сбрасывает всю файловую систему в один файл и обычно делает это быстрее, чем tar
жестяная банка. Это утилита для конкретной файловой системы, поэтому она может использовать внутренние функции fs так, как tar не может.
Я бы посоветовал вам сначала попробовать перейти на EXT4, если вы еще не используете его.
Google провел много исследований почему EXT4 - хорошая идея.
После этого вам следует изучить развертывание архитектуры распределенной файловой системы. Например:
Возможно, это упрощенный ответ, но моей первой мыслью было использовать что-то вроде GridFS который построен на MongoDB. Многие драйверы основного языка поддерживают его прямо из коробки, поэтому вы сможете просто заменить его на разделы вашего кода, читающие файлы. Кроме того, вы можете просто сделать существующие пути к каталогам ключами к этим файлам.
Одна из проблем, которые могут возникнуть у вас, заключается в том, что Mongo имеет тенденцию довольно быстро замедляться, если он все время ищет с диска. Я ожидаю, что с 10 миллионами файлов большая часть ваших данных будет на диске. Насколько я помню, блоки файлов в GridFS имеют размер 4 МБ, поэтому, если ваши файлы больше этого размера, вам придется выполнить несколько дорогостоящих операций, чтобы получить один файл. Я думаю, что ключевым моментом будет сегментирование ваших файлов на основе вашей и без того аккуратной структуры каталогов, чтобы у вас могло быть несколько экземпляров Mongo, работающих на нескольких компьютерах, чтобы облегчить нагрузку. Однако я также не знаю, каковы ваши требования к производительности, поэтому, возможно, я слишком много думаю об этом.
Какая от всего этого польза? Производительность, которая довольно близко соответствует чтению с диска если все сделано правильно. Также, Mongo имеет несколько отличных встроенных способов резервного копирования. весь объем данных в инстансе БД быстро, даже при работающей базе данных.
Если вас устраивает модель устройства для хранения данных, возможно, вы могли бы рассмотреть NexentaStor. Он запускает ZFS на OpenSolaris под капотом, но все администрирование осуществляется через веб-интерфейс.
Есть несколько функций, которые помогут решить вашу проблему.
Версия Enterprise поддерживает форму удаленной репликации на основе моментальных снимков, которая не требует сканирования всей файловой системы.
Если вы не против испачкать руки, у ZFS есть очень удобный ZFS diff Команда, которая эффективно сообщает вам, какие файлы были добавлены, изменены или удалены с момента последнего моментального снимка, без необходимости сканирования всей файловой системы. Вы можете включить это в свою систему резервного копирования, чтобы значительно сократить время, необходимое для выполнения инкрементного резервного копирования.
Вы можете использовать стандартный dump
Утилита Для резервного копирования файловой системы EXT4 с большим количеством файлов. Эта утилита сначала проверяет, какие блоки используются в файловой системе, а затем создает их резервные копии в порядке диска, устраняя большинство запросов.
Соответствующий restore
утилита для восстановления резервных копий, созданных dump
.
Он поддерживает инкрементное резервное копирование с использованием уровней - файлы резервных копий уровня 1, измененные с последней резервной копии уровня 0 (полной), уровень 2 - измененные с резервной копии уровня 1 и так далее.
Для инкрементных резервных копий одним из вариантов было бы иметь второе теневое дерево для новых обложек. То есть у вас будет главное дерево, которое используется для всех операций чтения. У вас также будет newfiles/012345.....jpg
каталог; недавно добавленные обложки создают жесткую ссылку здесь, а также в основном дереве. При выполнении резервного копирования вы можете иногда создавать резервную копию основного дерева, но резервное копирование (гораздо меньшего размера) newfiles
дерево намного чаще.
Обратите внимание, что для сохранения newfiles
tree small, перед выполнением новой резервной копии основного дерева вы можете очистить дерево newfiles:
mv newfiles newfiles_
mkdir newfiles
rm -rf newfiles_
Как только вы это сделаете, вы, конечно же, обязуетесь создать новую резервную копию главного дерева.
Обычно помогает добавление немного параллелизма.
У меня такая же проблема, как и у вас; в моем случае мне нужно создать резервную копию около 30 миллионов файлов, большинство из которых являются файлами HTML, PHP или JPEG. Для меня BackupPC + rsync over ssh вроде нормально работает; полное резервное копирование занимает около одного дня, но инкрементное резервное копирование обычно завершается за пару часов.
Хитрость заключается в том, чтобы добавить каждый каталог основного уровня (0, 1, 2 ... a, b, c ...) в качестве новой цели для копирования в BackupPC и позволить ему выполнять резервное копирование параллельно, так что он одновременно выполняет резервное копирование каталогов. а /, б /, c / * и так далее. В зависимости от вашей дисковой подсистемы, что-либо от пары процессов до примерно 10 процессов, вероятно, является самым быстрым способом резервного копирования.
Снимки LVM и резервное копирование на уровне блоков также возможны, но с помощью BackuPC и резервного копирования на уровне файлов вы все равно можете восстанавливать отдельные файлы или каталоги, если это необходимо.
Бенджамин,
Я думаю, что ваша проблема может быть решена с помощью количества файлов на уровне каталога!
Существенно ли меняется время доступа, если вы храните в каталоге 20 000 файлов?
Также вы хотели хранить метаданные файловой системы на отдельном диске с более быстрым доступом? (Например, SSD).
Вместо этого я бы порекомендовал старую добрую реляционную базу данных.
Я бы использовал PostgreSQL, скажем, с 256 секционированными таблицами (cover_00, cover_01, ..., cover_ff) с данными изображения как bytea
(двоичный) столбец с внешним хранилищем, с идентификатором файла в качестве первичного ключа. Получение изображения будет быстрым (благодаря индексу по первичному ключу), целостность данных будет гарантирована (база данных, совместимая с ACID), резервное копирование будет в порядке диска, поэтому не будет слишком много поиска.