MappedByteBuffer с отображением в память или DirectBuffer для реализации БД?

Это выглядит как длинный вопрос из-за всего контекста. Есть 2 вопроса внутри романа ниже. Спасибо, что нашли время, чтобы прочитать это и оказать помощь.

ситуация

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

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

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

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

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

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

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

дизайн

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

Все идет нормально...

Проблемы

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

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

Когда я думаю об этом дизайне, скажем, даже с использованием 1024 МБ размеров mmap, для СУБД, на которой размещены несколько огромных баз данных, представленных, скажем, файлами по 1 ТБ, я теперь имеютысячи областей отображения в памяти и в моем собственном тестировании в Windows 7, пытаясь создать несколько сотен карт на файл размером несколько ГБ, я не просто столкнулся с исключениями, я фактически заставлял JVM работать с segfault каждый раз, когда пытался выделил слишком много и в одном случае получил видео на моем компьютере с Windows 7, чтобы вырезать и заново инициализировать с помощью всплывающего сообщения об ошибке ОС, которого я никогда раньше не видел.

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

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

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

Вопрос 1 из 2

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

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

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

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

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

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

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

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

Вопрос № 2 из 2

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

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

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