2012-02-13 15 views
21

Это похоже на длинный вопрос из-за всего контекста. В романе есть два вопроса. Спасибо, что нашли время, чтобы прочитать это и оказать помощь.Memory-Mapped MappedByteBuffer или Direct ByteBuffer для реализации БД?

Ситуация

Я работаю на масштабируемой реализации хранилища данных, которая может поддерживать работу с файлами данных от нескольких килобайт до туберкулеза или более размеров в системе 32-разрядной или 64-разрядной.

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

В системе может располагаться 1 или более база данных; каждый из которых представлен файлом на диске.

Детали реализации не важны; единственной важной деталью является то, что мне нужно постоянно добавлять файл и расширять его с КБ, до МБ, до ГБ до ТБ и в то же время случайным образом пропускать файл для операций чтения, чтобы отвечать на запросы клиентов.

Первоклассники Мысли

На первый взгляд, я знал, что я хотел бы использовать отображаемые в памяти файлы, так что я мог бы подтолкнуть бремя эффективно управлять государством в памяти данных на хост-ОС и из мой код.

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

Дизайн

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

До сих пор так хорошо ...

Проблемы

Это где я начал зацикливаться и думать, что происходит с другим дизайном (предложенной ниже) может быть лучшим способом сделать это.

Из приблизительно 20 или около того вопросов, связанных с памятью, здесь, на SO, кажется, что вызовы mmap чувствительны к желанию непрерывных прогонов памяти при распределении. Так, например, на 32-битной ОС хоста, если я попытался создать файл размером 2 ГБ, из-за фрагментации памяти, мои шансы тонкие, что сопоставление будет успешным, и вместо этого я должен использовать что-то вроде серии из 128 МБ-сопоставлений, чтобы вытащить целую файл в.

Когда я думаю, что дизайн, даже сказать, используя размеры 1024MB MMAP для СУБДА хостинг до нескольких огромных баз данных все представленный, скажем, на 1 ТБ файлов, у меня теперь есть тысяч из памяти отображенных областей в памяти и в моем собственном тестировании на Windows 7, пытаясь создать несколько сотен mmaps в файле с несколькими GB, я не просто столкнулся с исключениями, я фактически получил JVM для segfault каждый раз, когда я пытался выделить слишком много и в одном случае получил видео на моей машине Windows 7, чтобы вырезать и повторно инициализировать с помощью всплывающего окна OS-error, которое я никогда раньше не видел.

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

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

Я могу в какой-то мере побороть это, увеличив файл в кусках (скажем, 8 Мбайт за раз) и только заново создаст сопоставление каждые 8 ​​МБ, но необходимость постоянно воссоздавать эти сопоставления заставит меня нервничать, особенно с нет явно unmap feature supported in Java.

Вопрос № 1 из 2

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

Но затем я оглядываюсь вокруг ландшафта вокруг меня с такими решениями, как MongoDB, охватывающие файлы с отображением памяти повсюду, и я чувствую, что у меня отсутствует какой-то основной компонент здесь (я знаю, что он выделяет что-то вроде 2 ГБ экстентов при время, поэтому я предполагаю, что они работают с стоимостью повторной карты с этой логикой и помогают поддерживать последовательные прогоны на диске).

На данный момент я не знаю, является ли проблема отсутствием Java-операции unmap, которая делает это намного более опасным и непригодным для моих целей или если мое понимание неверно, и кто-то может указать мне на север.

Альтернативный дизайн

Альтернативный дизайн отображенного в память предложенному выше, что я пойду с, если мое понимание ттар правильно выглядит следующим образом:

Определение a direct ByteBuffer разумного настраиваемым размером (2, 4, 8, 16, 32, 64, 128 КБ), что делает его легко совместимым с любой платформой хоста (не нужно беспокоиться о том, что сама СУБД вызывает сценарии переполнения) и используя оригинальный FileChannel, выполните specific-offset reads файла 1 объем памяти-буфера одновременно, полностью отменяя файлы с отображением памяти.

Недостатком является то, что теперь мой код должен беспокоиться о таких вещах, как «Я достаточно читал из файла, чтобы загрузить полную запись?»

Другой недостаток заключается в том, что я не могу использовать логику виртуальной памяти ОС, позволяя ей автоматически сохранять более «горячие» данные в памяти; вместо этого мне просто нужно надеяться, что логика кэша файлов, используемая ОС, достаточно велика, чтобы сделать что-то полезное для меня здесь.

Вопрос № 2 из 2

Я надеялся получить подтверждение моего понимания всего этого.

Например, возможно, кеш-файл является фантастическим, что в обоих случаях (отображение в память или прямое чтение) операционная система будет поддерживать как можно больше моих горячих данных, а разница в производительности для больших файлов незначительна.

Возможно, мое понимание чувствительных требований к файлам с отображением памяти (непрерывная память) неверно, и я могу игнорировать все это.

+0

Если вы получили некоторое представление, так как задавать свой вопрос, пожалуйста, напишите их как ответ. Многие люди читали этот вопрос, и они могли использовать проницательность. Там тонна «не исправит» ошибки вокруг mmapping, как http://bugs.sun.com/view_bug.do?bug_id=6893654 (хотя JVM segfault и сбой графического драйвера еще хуже!) Интересно, как просто , элегантная собственная функция становится сложной и уродливой в управляемом мире. –

+0

@AleksandrDubinsky вы совершенно правы (об элегантном становлении inelegant) - мои окончательные результаты заключаются в том, что файлы mmap'ed не могут быть созданы быстро, не введя значительную нестабильность в систему (я не знаю, прояснился ли я в этой теме, но Мне удалось синей экранной машиной windows dev). Эта деталь ALONE заставила меня хотеть придерживаться использования AsyncFileChannel для ввода/вывода файлов и избегать mmap все вместе, хотя Питер (ниже) имел значительный успех в Chronicle. –

+0

@AleksandrDubinsky Как только я смог привести VM и мою машину в колени с очевидным «неправильным использованием» mmapped-файлов, я покончил с этим путем. Они элегантны и предлагают фантастическую производительность, но из большего количества чтения, которое я сделал в AsyncFileChannel, кажется, что вы можете приблизиться к той же производительности (позволяя ОС использовать FS и контроллер диска и порядок ввода-вывода для оптимизации запросов). Если вы действительно хотите спуститься по пути mmap, то здесь Питер. –

ответ

15

Вы могли бы быть заинтересованы в https://github.com/peter-lawrey/Java-Chronicle

В этом я создать несколько отображений памяти в том же файле (размер является мощность 2 до 1 Гб) Файл может быть любого размера (до размера ваш жесткий диск)

Он также создает индекс, чтобы вы могли найти любую запись наугад, и каждая запись может быть любого размера.

Он может использоваться совместно между процессами и использоваться для событий с низкой задержкой между процессами.

Предполагаю, что вы используете 64-разрядную ОС, если хотите использовать большие объемы данных. В этом случае вам будет нужен список MappedByteBuffer. Имеет смысл использовать правильные инструменты для работы. ;)

Я нашел его производительность хорошо, даже с размерами данных по всему 10x вашей основной памяти (я использую быстрый SSD диск так YMMV)

+0

не понимал, что вы были автором хроники; Спасибо за ответ. Как вы обрабатываете запись в файл, через MBB или вы просто вызываете FileChannel напрямую, и каждый раз, когда происходит чтение, выходит за пределы MBB дальнейших действий, вы просто создаете новый файл и добавляете его в свой список данныхBuffers? Основная информация, которую я пропускаю, - это то, что * lots * больших сопоставленных файлов делает для использования памяти хост-системы. (продолжение в следующем комментарии ...) –

+0

, так как существует требование «смежного RAM» при mem-сопоставлении файла, скажем, я решаю что-то безопасное, например 64 или 128 МБ, и по мере того, как файл DB растет и запросы поступают данные за пределами существующих отображаемых границ я просто создаю больше на лету.Тогда давайте скажем, что мой файл данных попадает в 100s GB, и у меня есть 100s, если не 1000 mem-отображаемых байт-буферов ... похоже, я настраиваю свой компьютер для запуска пейджинга, как сумасшедший, когда VM заполняется. Я хочу быть в курсе случаев, связанных с ошибками, а недостатки - суть того, что я прошу. –

+0

Каждый файл с сопоставлением памяти несколько дороже (у меня нет точных данных). Я знаю, что если вы создаете много отображений в 1 МБ, у вас заканчиваются ресурсы довольно быстро. Однако, если вы используете буферы 1 ГБ, вы можете создать файл размером 8 ТБ. Вы можете определить, сколько для вашей системы слишком много, создав много маленьких (например, 4 КБ). –

2

Думаю, вам не стоит беспокоиться о файлах mmap'ping размером до 2 ГБ.

Рассматривая источники MongoDB в качестве примера БД, использующие файлы с отображением памяти, вы всегда найдете полный файл данных в MemoryMappedFile::mapWithOptions() (который вызывает MemoryMappedFile::map()). Данные БД охватывают несколько файлов размером до 2 ГБ. Также он предопределяет файлы данных, поэтому нет необходимости переназначать по мере роста данных, что предотвращает фрагментацию файлов. Как правило, вы можете вдохновить на исходный код этой БД.

+1

@Thomas Я обновил ссылки, но я думаю, что код в значительной степени устарел, с тех пор MongoDB претерпел множество изменений. – pingw33n

 Смежные вопросы

  • Нет связанных вопросов^_^