Настройка tmpfs `/run/lock` для сотен тысяч файлов блокировок по 0 байт и работа с лимитом inode
У меня есть ситуация, когда мне нужно создать сотни тысяч файлов блокировок по 0 байт для контроля параллелизма.
Я протестировал создание их с помощью:
for i in `seq 1 50000`; do touch "/run/lock/${i}.lock"; done
Поскольку файлы имеют размер 0 байт, они не занимают места в разделе. Смотря на df -h
:
Filesystem Size Used Avail Use% Mounted on
tmpfs 50M 344K 49M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 246M 0 246M 0% /run/shm
none 100M 0 100M 0% /run/user
0%
фигура не меняется вообще в /run/lock
строка.
Однако объем памяти увеличивается в среднем примерно на 1 КБ на файл блокировки. Я обнаружил это путем сравнения free -h
до и после создания 70000 файлов блокировки внутри /run/lock
, Это увеличение памяти было отражено в реальном использовании памяти (виртуальная память минус буферы / кэш).
Позже я обнаружил, что это увеличение на 1 КБ, скорее всего, связано с инодами. Поэтому я проверил использование inode с помощью df -i
:
Filesystem Inodes IUsed IFree IUse% Mounted on
tmpfs 62729 322 62407 1% /run
none 62729 50001 12728 80% /run/lock
none 62729 1 62728 1% /run/shm
none 62729 2 62727 1% /run/user
Как вы можете видеть, файлы блокировки увеличивают иноды внутри /run/lock
раздел.
Я в настоящее время на Ubuntu и /run
крепления не отражаются внутри /etc/fstab
, Бег mount
дает мне:
tmpfs on /run type tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
none on /run/lock type tmpfs (rw,noexec,nosuid,nodev,size=5242880)
none on /run/shm type tmpfs (rw,nosuid,nodev)
none on /run/user type tmpfs (rw,noexec,nosuid,nodev,size=104857600,mode=0755)
У меня есть пара вопросов по этому поводу (но первый самый важный):
- Как я могу увеличить предел инодов навсегда для
/run/lock
? Так что этот предел переживает перезапуски? - Было бы лучше для меня создать свой собственный каталог и смонтировать на нем tmpfs, чтобы использовать его вместо использования
/run/lock
? - Является ли ограничение размера каждого раздела полностью независимым друг от друга? Это хранит файлы в
/run
похоже не влияет/run/lock
и наоборот. - 1KB получен из инода? Я заметил, что при создании непустых файлов базовый блок составляет 4 КБ для каждого файла.
- Почему
/run
учитывая тип файловой системыtmpfs
но/run/lock
,/run/shm
,/run/user
указать тип файловой системы "none", тем более что все они поддерживаются TMPFS? Почему они все не читаются какtmpfs
вFilesystem
столбец? - Если все каталоги независимо ограничены, как OOM killer обрабатывает ситуацию, когда имеется несколько полных разделов TMPFS, каждый из которых имеет размер до 50% ОЗУ, и где также существуют процессы, борющиеся за ОЗУ. Очевидно, что нельзя использовать более 100% оперативной памяти. Согласно https://www.kernel.org/doc/Documentation/filesystems/tmpfs.txt нем упоминается, что система заблокирована. Как это работает?
2 ответа
Отвечая на некоторые ваши вопросы, по порядку:
- Ты можешь использовать
mount -o remount,nr_inodes=NUM /run/lock
в вашем скрипте запуска приложения (в случае, если он запускается с uid=0). Также должно быть безопасно добавить соответствующую строку в / etc / fstab, но не проверено. - Разделение здесь имеет некоторый смысл, так как в случае заполнения все inode не будут мешать остальной системе.
- Да, полностью независимый.
- [...]
- С виртуальными файловыми системами (основанными не на блочных устройствах), вы можете указать в качестве команды монтирования любое устройство, это имеет значение только для типа.
- [...]
Не уверен, что ваше приложение создаст пустые файлы, открыв его (и как долго), но вы можете также рассмотреть возможность увеличения лимита открытых файлов (проверьте ulimit), чтобы избежать истощения.
Вы идете об этом в неправильном направлении. Вы можете использовать семантику файловой системы для обеспечения согласованности.
Если вы хотите прочитать файл, просто откройте и прочитайте его. Вы должны всегда использовать
open
, никогдаaccess
для этой операции. Если вы используете для этого библиотеку PHP, убедитесь, что она просто вызываетopen
и неaccess
в файле - ноfopen
должно работать нормально.Когда вы хотите обновить или создать новый файл, вы выполняете следующие операции:-
- Создайте новый файл, используя механизм создания временного файла. Если он не существует - создайте новое имя файла, которое вряд ли существует (filename.XXXXXX, где X заменяется случайными символами). Обязательно откройте в O_EXCL.
- Запишите соответствующие данные в файл.
- Переименуйте файл в имя старого файла.
Это операционно безопасно, потому что переименования определены как атомарные. Читатель, открывающий файл, увидит либо старый файл, либо новый файл, но никогда не будет несуществующим файлом в кэше.
В худшем случае при множестве одновременных проверок каждого файла несколько авторов кратко перезаписывают друг друга. Но это намного дешевле, чем использование блокировки файлов для каждого файла.
В качестве альтернативы, вместо того, чтобы иметь файл блокировки для каждого файла - рассмотрите просто блокировку каждого отдельного объекта кеша напрямую. Я все еще не думаю, что это масштабируется как бы то ни было.
С помощью rename
а также link
семантика в этом случае гарантирует согласованность с вашим кешем и намного дешевле в управлении, чем блокировка файлов.