Як вирішити ліміт кількості підкаталогів Linux?


9

У мене є веб-сайт, на якому зберігатимуться зображення профілю користувача. Кожне зображення зберігається у каталозі (Linux), специфічному для користувача. Наразі у мене є клієнтська база 30+, це означає, що у мене буде 30+ папок. Але мій поточний вікно Linux (ext2 / ext3) не підтримує створення більше 32000 каталогів. Як мені пройти це? Навіть хлопці YouTube мають таку саму проблему із мініатюрами відео. Але вони вирішили це, переїхавши до ReiserFS. Чи не можемо ми мати краще рішення?

Оновлення: На запит в IRC люди запитували про оновлення його до ext4, який має обмеження 64k, і, звичайно, ви навіть можете пройти це . Або злом ядра, щоб змінити ліміт.

Оновлення: як щодо розділення бази користувачів на папки на основі діапазону userid. Значення 1-1000 в одній папці, 1000-2000 в іншій. Це здається простим. Що ви кажете, хлопці?

Чесно кажучи, чи немає іншого способу?


1
Чому ви не хочете змінити файлову систему? Якщо це обмеження ext2 / 3, у вас не буде нічого іншого, крім зміни файлової системи або розділення поточного FS на більш невеликі FS (більше різних точок монтажу).
Мануель Фокс

1
Мануель: Якщо він змінить файлову систему, він прив’язує до своєї програми певний FS. Хоча це може в кінцевому підсумку відповісти, я вважаю, що це, мабуть, проблема, яку потрібно вирішити на рівні програми. Якщо вам потрібно зламати ядро ​​або файлову систему, ви, ймовірно, йдете по неправильному шляху, якщо не будуть виконані якісь особливі вимоги.
Кайл Брандт

Відповіді:


16

Цей ліміт призначений для довідника, не для всієї файлової системи, тому ви можете обійти його шляхом подальшого поділу речей. Наприклад, замість того, щоб усі підкаталоги користувачів в одному каталозі розділили їх на перші два символи імені, щоб у вас вийшло щось на кшталт:

top_level_dir
|---aa
|   |---aardvark1
|   |---aardvark2
|---da
|   |---dan
|   |---david
|---do
    |---don

Ще краще було б створити певну форму хешу імен і використовувати її для поділу. Таким чином ви отримаєте краще поширення серед каталогів замість того, щоб, наприклад, початкові букви "da" були дуже заповнені, а "zz" повністю порожніми. Наприклад, якщо ви візьмете ім'я CRC або MD5 і використовуєте перші 8 біт, ви отримаєте щось подібне:

top_level_dir
|---00
|   |---some_username
|   |---some_username
|---01
|   |---some_username
...
|---FF
|   |---some_username

Це може бути розширено на подальші глибини, якщо потрібно, наприклад, якщо так, якщо використовувати ім'я користувача не хеш-значення:

top_level_dir
|---a
|   |---a
|       |---aardvark1
|       |---aardvark2
|---d
    |---a
    |   |---dan
    |   |---david
    |---o
        |---don

Цей метод застосовується в багатьох місцях, наприклад, кеш-пам'ять кальмарів, для копіювання прикладу Людвіга та локальних кешів веб-браузерів.

Важливо відзначити, що з ext2 / 3 ви почнете стикатися з проблемами продуктивності, перш ніж наблизитись до межі 32 000, оскільки каталоги шукаються лінійно. Перехід до іншої файлової системи (наприклад, ext4 або Райзер) призведе до усунення цієї неефективності (Райзер здійснює пошук каталогів з двійковим розбиттям алгоритму, тому довгі каталоги обробляються набагато ефективніше, ext4 може робити це теж), а також фіксований ліміт на каталог.


Щойно оновив опис запитання, щоб включити таке: "Оновлення: як щодо розділення бази користувачів на папки на основі діапазону userid. Значення 1-1000 в одній папці, 1000-2000 в іншій подібній. Це здається простим. Що ти кажеш? "
None-да

1
Це було б добре і було б більш ефективним, ніж хеш, якщо користувачі, як правило, ідентифікуються за ідентифікатором користувача замість (або як) ім'я користувача. Хоча якщо ви завжди посилаєтесь на них по імені в інших місцях системи, вам доведеться додавати додаткові пошукові імена>> id в усьому місці.
Девід Спіллетт

Спасибі Давиде! Я спробував навіть інше рішення. Я створив навряд чи 4 папки з діапазоном 1-30000, 30000-60000 тощо. Я думаю, що отримання файлу з такого великого каталогу займе більше часу, ніж з каталогу, який містить 1000 файлів (попередній підхід). Що ти сказав?
None-да

1
Це залежить від файлової системи. Якщо ви використовуєте ext2 або ext3, я рекомендував би набагато менше 30 000 за каталог. Деякі інструменти видають попередження про близько 10 000. Ви можете ввімкнути індексацію каталогів у ext3 / 4, щоб допомогти: tune2fs -O dir_index / dev / <volumename>, але просто збереження кількості об'єктів у каталозі нижче (пару тисяч чи менше?) - це те, що я рекомендую тут .
Девід Спіллетт

@Maddy, ви хочете це рішення через інші обмеження в тому, як Ext2 / 3 обробляє велику кількість файлів. Для детальної інформації див. Сервер default.com/questions/43133/… . Розбивання імен у відрізках підкаталогів усуває інші проблеми, з якими ви могли б зіткнутися з часом. Зауважте, що це та сама стратегія, яку використовує Squid, коли вперше створює об’єктний кеш - наприклад, 64 каталоги, у кожному із яких 64 каталоги, як приклад.
Avery Payne

7

Якщо ви зобов'язані ext2 / ext3, я бачу єдину можливість розділити ваші дані. Знайдіть критерій, який розбиває ваші дані на керовані фрагменти подібного розміру.

Якщо мова йде лише про зображення профілів, які я б робив:

  1. Використовуйте хеш (наприклад, SHA1) зображення
  2. Використовуйте SHA1 як ім'я файлу та каталогу

Наприклад, кеш SQUID робить це так:

f / 4b / 353ac7303854033

Каталог верхнього рівня - перша шістнадцяткова цифра, другий рівень - дві наступні шістнадцяткові цифри, а ім'я файлу - інші шістнадцяткові цифри.


2

Не маємо кращого рішення?

У вас є краще рішення - використовуйте іншу файлову систему, є багато доступних, багато з яких оптимізовані під різні завдання. Як ви вказали, ReiserFS оптимізований для обробки багатьох файлів у каталозі.

Дивіться тут для порівняння файлових систем.

Тільки радійте, що ви не зациклювались на NTFS, який справді неприйнятний для багатьох файлів у каталозі. Я рекомендую JFS як заміну, якщо ви не хочете використовувати відносно новий (але, мабуть, стабільний) ext4 FS.


Чи є у вас хороші посилання на продуктивність файлової системи NTFS?
Thorbjørn Ravn Andersen

так, за винятком особистого досвіду роботи з додатком, який був занадто довгим, створюючи нові файли в каталозі .. (для видалення їх знадобилося кілька годин), і підвищення продуктивності підривної системи обмеженням кількості файлів у каталозі до 1000. Або читайте : support.microsoft.com/kb/130694 Я не думаю, що вони ніколи не "виправляли" це, як це все ще відзначалося як парф. налаштування для NTFS.
gbjbaanb

1

Чи невелике зображення профілю? А що з тим, як помістити його в базу даних з рештою даних профілю? Це може бути не найкращим варіантом для вас, але варто задуматися ...

Ось (старіший) документ Microsoft на тему: BLOB чи ні BLOB .


1

Я зламав разом невеличку веб-галерею, де я закінчився варіантом цієї проблеми; Я "тільки" мав ~ 30 000 зображень у каталозі кешу, що виявилося досить повільним (ext2 використовує пов'язані списки для індексів каталогів, наскільки я його пам’ятаю).

Я закінчив щось робити за цими напрямками:

def key2path(key):
    hash = md5(key)
    return os.path.join(hash[0], hash[1], key)

Це дозволить розділити дані в 256 каталогах, що дає швидкий пошук каталогів для кожного з трьох рівнів.

  • Я вирішив використовувати MD5 над SHA-1, оскільки MD5 гарантує інший вихід, якщо ви зміните будь-які 12 біт із 32, тому я вважаю, що це добре підходить до хеш-імен користувачів, каталогів та інших коротких речей. І це теж швидко ...
  • Я не включаю весь хеш, оскільки він створить занадто багато каталогів і ефективно переробляє кеш диска знову і знову.

1
Можливо, ви могли б використовувати більш простий хеш, як CRC, оскільки хеш не повинен бути криптографічно сильним, як MD5 або SHA ... але різниця в продуктивності, мабуть, все-таки незначна ...
sleske

0

Не негайна відповідь на вашу проблему, але щось, на що слід звернути увагу, - це проект, пов'язаний з OpenBSD, який називається "Epitome"

Epitome - це двигун, який надає послуги єдиного зберігання, зберігання вмісту та дедуплікації вмісту.

Всі ваші дані зберігаються в сховищі даних як хешовані блоки, видаляючи не унікальні блоки, щоб зменшити використання місця, і дозволяє вам по суті забути про механізм зберігання, оскільки ви можете просто запитати вміст із сховища даних UUID.

Наразі Epitome є експериментальним, але варто дивитись на майбутнє.


0

Як правило, ви хочете уникати наявності каталогів з великою кількістю файлів / каталогів. Основна причина полягає в тому, що розширення підстановки в командному рядку призведе до помилок "Занадто багато аргументів", що призводить до сильного болю при спробі роботи з цими каталогами.

Знайдіть рішення, яке робить глибше, але вузьке дерево, наприклад, створивши підпапки, як описали інші.


0

У нас була подібна проблема, рішення - як згадувалося раніше - полягає у створенні ієрархії каталогів.

Звичайно, якщо у вас є складна програма, яка спирається на плоску структуру каталогів, можливо, вам знадобиться багато виправлення. Тому добре знати, що існує рішення, використовуйте символьні посилання, які не мають згаданого обмеження 32k. Тоді у вас є достатньо часу, щоб виправити додаток ...


0

Чому б не використовувати підхід часової позначки, а потім мати варіант переповнення.

Наприклад

Тож скажімо, що ваша часова марка: 1366587600

Пропустіть останні дві цифри (інакше це стає просто смішно). Розділіть штамп на набори 4 (кількість директорій не повинна перевищувати 9999 - якщо ви хочете, ви можете розділити його по-іншому).

Це повинно дати вам щось подібне:

/files/1366/5876/

Потім також перевірте суму в dir перед завантаженням, якщо вона отримує велику кількість завантажень (тобто 32000 + за 100 секунд), а потім повторіть каталог другим або листом, наприклад:

/files/1366/5876/a/file.txt

або

/files/1366/5876/00/file.txt

Потім введіть часову позначку + літеру або повний код шляху в db разом з користувачем, і вам слід встановити.

марка шляху: 1366587600 або 13665876a (якщо ви використовуєте букви).

Це закінчується великою кількістю каталогів, але це може бути дуже корисно для обробки версій файлів. Наприклад, якщо користувач хоче використати нову картинку профілю, у вас все ще є стара версія старого, якщо вона хоче скасувати зміни (її не просто переписано).


0

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

Тоді вам потрібно перетворити свій ідентифікатор користувача, щоб вони починалися з 1.

Тоді ви можете зробити: modulo = currentId % numberOfSubdirectories

moduloтепер буде містити номер вашого підкаталогу, який ніколи не буде більшим, ніж numberOfSubdirectoriesви вибрали.

Робіть все, що завгодно, з модулем, наприклад, хеш.

Також таким чином підкаталоги будуть заповнюватися лінійно.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.