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
Я надеялся получить подтверждение моего понимания всего этого.
Например, возможно, файловый кеш является фантастическим, что в обоих случаях (отображение памяти или прямое чтение) хост-операционная система будет сохранять как можно больше моих горячих данных, а разница в производительности для больших файлов незначительна.
Или, может быть, мое понимание чувствительных требований к отображенным в память файлам (непрерывной памяти) неверно, и я могу игнорировать все это.