Файлы, не закрывающиеся на BTRFS, и старые версии снова появляются
После большого количества тестирования и поиска справочных страниц по BTRFS мне нужна помощь некоторых пользователей Linux / BTRFS.
У меня есть Java-приложение, которое записывает файлы данных на диск с помощью утилиты java MappedByteBuffer. Это приложение использует буфер байтов ~16000 байтов при записи на диск. Когда новый файл записывается в него, создается временный файл с размером буфера, и из-за реализации java-файлов с расширением mem код не закрывает файл явно. Вместо этого мы вызываем Linux drop_caches, чтобы принудительно сбросить неиспользуемые карты памяти на диск.
- На EXT4 эти файлы автоматически закрываются и размер файла корректно корректируется.
- В BTRFS эти файлы остаются размером ~16000 байт и в них отсутствуют некоторые данные (возможно, проблемы с подкачкой)
- На BTRFS, когда я удаляю эти файлы, и программное обеспечение перезапускается и снова создает файлы, одна и та же проблема возникает каждый раз, И даты изменения относятся к моменту, когда файлы были изначально созданы.
Информация о сервере: мы работаем с последней версией Centos 7.2 и обновляем патчи
- ОС Centos 7 x64 (ядро 3.10.0-514.10.2.el7.x86_64)
- btrfs-progs v4.4.1
- Java 1.8.0_111
Тестирование выполнено
У нас есть сервер реплики, работающий на Ext4, и эта проблема не возникает
В настоящее время мы используем COW и сжатие, поэтому я попытался отключить их, перезагрузить, удалить старые данные и перезапустить программное обеспечение. Проблема все еще возникла
- Я также попытался отключить space_cache, recovery, и я также попытался установить commit=5 с помощью flushoncommit... это также не помогло не закрывающимся файлам / неправильным датам изменения
1 ответ
и из-за реализации Java-файлов, отображаемых в формате Java, код явно не закрывает файл.
Это не имеет особого смысла. Отображения памяти с файловой поддержкой не требуют, чтобы их файловые дескрипторы оставались открытыми. Таким образом, вы абсолютно можете закрыть файл после создания сопоставленного буфера.
Вместо этого мы вызываем Linux drop_caches, чтобы принудительно сбросить неиспользуемые карты памяти на диск.
Это огромное излишество.
- используйте MappedByteBuffer::force для синхронизации изменений на диске
- переименовать временный файл
- fsync каталог, необходимый после переименования для обеспечения устойчивости к сбоям (см. ссылки ниже).
try(FileChannel dir = FileChannel.open(Paths.get("/path/directory"), StandardOpenOptions.READ)) {
dir.force(true);
}