Jak rozwiązać limit liczby podkatalogów Linux?

9

Mam stronę internetową, w której będą przechowywane obrazy profilów użytkowników. Każdy obraz jest przechowywany w katalogu (Linux) specyficznym dla użytkownika. Obecnie mam bazę klientów ponad 30, co oznacza, że ​​będę miał ponad 30 folderów. Ale mój obecny system Linux (ext2 / ext3) nie obsługuje tworzenia więcej niż 32000 katalogów. Jak sobie z tym poradzić? Nawet faceci z YouTube mają ten sam problem z miniaturami wideo. Ale rozwiązali to, przechodząc do ReiserFS. Czy nie możemy znaleźć lepszego rozwiązania?

Aktualizacja: Zapytani w IRC, ludzie pytali o uaktualnienie go do ext4, który ma limit 64k i oczywiście możesz go nawet ominąć . Lub hakowanie jądra w celu zmiany limitu.

Aktualizacja: Co powiesz na podzielenie bazy użytkowników na foldery na podstawie zakresu identyfikatora użytkownika. Oznacza to 1-1000 w jednym folderze, 1000-2000 w innym podobnym. To wydaje się proste. Co powiecie chłopaki?

Szczerze mówiąc, czy nie ma innego sposobu?

Brak danych
źródło
1
Dlaczego nie chcesz zmienić systemu plików? Jeśli jest to ograniczenie ext2 / 3, nie będziesz miał żadnych innych zmian niż zmiana systemu plików lub podział obecnego FS na więcej mniejszych FS (więcej różnych punktów montowania).
Manuel Faux
1
Manuel: Jeśli zmieni system plików, przywiąże określony FS do swojej aplikacji. Chociaż może to być odpowiedź, chciałbym, aby był to prawdopodobnie problem, który należy rozwiązać na poziomie aplikacji. Jeśli musisz zhakować jądro lub system plików, prawdopodobnie podążasz niewłaściwą ścieżką, chyba że są jakieś specjalne wymagania.
Kyle Brandt

Odpowiedzi:

16

Limit ten dotyczy poszczególnych katalogów, a nie całego systemu plików, więc można obejść ten problem, dzieląc rzeczy dalej. Na przykład zamiast umieszczać wszystkie podkatalogi użytkowników w tym samym katalogu, dzieląc je na dwa pierwsze znaki nazwy, aby uzyskać coś takiego:

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

Jeszcze lepiej byłoby stworzyć jakąś formę skrótów nazw i użyć jej do podziału. W ten sposób uzyskasz lepszą rozpiętość między katalogami zamiast, z przykładem pierwszych liter, „da” jest bardzo pełny, a „zz” całkowicie pusty. Na przykład, jeśli weźmiesz nazwę CRC lub MD5 i użyjesz pierwszych 8 bitów, otrzymasz coś takiego:

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

W razie potrzeby można to rozszerzyć na dalsze głębokości, np. Jeśli używasz nazwy użytkownika, a nie wartości skrótu:

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

Ta metoda jest używana w wielu miejscach, takich jak pamięć podręczna kałamarnicy, aby skopiować przykład Ludwiga i lokalne pamięci podręczne przeglądarek internetowych.

Jedną ważną rzeczą do zapamiętania jest to, że z ext2 / 3 zaczniesz napotykać problemy z wydajnością, zanim zbliżysz się do limitu 32 000, ponieważ katalogi są przeszukiwane liniowo. Przeniesienie do innego systemu plików (na przykład ext4 lub reiser) usunie tę nieefektywność (reiser przeszukuje katalogi z algorimth z podziałem binarnym, więc długie katalogi są obsługiwane znacznie wydajniej, ext4 też może to zrobić), a także ze stałym limitem na katalog.

David Spillett
źródło
Właśnie zaktualizowałem opis pytania, aby zawierał następujące informacje: „Aktualizacja: Co powiesz na podział bazy użytkowników na foldery na podstawie zakresu identyfikatora użytkownika. Oznaczenie 1-1000 w jednym folderze, 1000-2000 w drugim podobnym. Wydaje się to proste. Co więc mówisz?"
None-da
1
To działałoby dobrze i byłoby bardziej wydajne niż skrót, jeśli użytkownicy są ogólnie identyfikowani za pomocą identyfikatora użytkownika zamiast (lub również) nazwy użytkownika. Chociaż jeśli zawsze odwołujesz się do nich po imieniu w innym miejscu w systemie, musisz dodać dodatkowe wyszukiwania name-> id w całym miejscu.
David Spillett
Dziękuję David! Próbowałem nawet innego rozwiązania. Nie utworzyłem prawie 4 folderów z zakresu 1-30000, 30000-60000 itd. Myślę, że uzyskanie pliku z tak dużego katalogu zajmie więcej czasu niż z katalogu zawierającego 1000 plików (poprzednie podejście). Co mówisz?
None-da
1
To zależy od systemu plików. Jeśli używasz ext2 lub ext3, polecam znacznie mniej niż 30 000 na katalog. Niektóre narzędzia wydają ostrzeżenia o 10 000. Możesz włączyć indeksowanie katalogów w ext3 / 4, aby pomóc: tune2fs -O katalog_danych / dev / <volumename>, ale po prostu utrzymanie niższej liczby obiektów w katalogu (kilka tysięcy lub mniej?) .
David Spillett
@Maddy, chcesz to rozwiązanie z powodu innych ograniczeń, w jaki sposób Ext2 / 3 obsługuje dużą liczbę plików. Aby uzyskać szczegółowe informacje, zobacz serverfault.com/questions/43133/ ... Podział nazw na podkatalogi „wiaderko-jako” łagodzi inne problemy, na które w końcu byś się natknął. Zauważ, że jest to ta sama strategia, z której korzysta Squid podczas pierwszej konfiguracji pamięci podręcznej obiektów - na przykład 64 katalogi z 64 katalogami wewnątrz, na przykład.
Avery Payne
7

Jeśli jesteś związany z ext2 / ext3, jedyną możliwością, jaką widzę, jest podzielenie danych na partycje. Znajdź kryterium, które dzieli dane na porcje o podobnej wielkości, które można zarządzać.

Jeśli chodzi tylko o zdjęcia profilowe, zrobiłbym:

  1. Użyj skrótu (np. SHA1) obrazu
  2. Użyj SHA1 jako nazwy pliku i katalogu

Na przykład pamięć podręczna SQUID robi to w ten sposób:

f / 4b / 353ac7303854033

Katalog najwyższego poziomu to pierwsza cyfra szesnastkowa, drugi poziom to kolejne dwie cyfry szesnastkowe, a nazwa pliku to pozostałe cyfry szesnastkowe.

Ludwig Weinzierl
źródło
2

Czy nie mamy lepszego rozwiązania?

Masz lepsze rozwiązanie - użyj innego systemu plików, dostępnych jest mnóstwo plików, z których wiele jest zoptymalizowanych do różnych zadań. Jak zauważyłeś, ReiserFS jest zoptymalizowany do obsługi wielu plików w katalogu.

Zobacz tutaj, aby porównać systemy plików.

Ciesz się, że nie utknąłeś z NTFS, który jest naprawdę fatalny dla wielu plików w katalogu. Polecam JFS jako zamiennik, jeśli nie masz ochoty używać stosunkowo nowego (ale podobno stabilnego) ext4 FS.

gbjbaanb
źródło
Czy masz dobre linki do wydajności systemu plików NTFS?
Thorbjørn Ravn Andersen
tak, oprócz osobistego doświadczenia z aplikacją, która pozostawała zbyt długo, tworząc nowe pliki w katalogu .. (zajęło to godziny, aby je wszystkie usunąć), a także zwiększenie wydajności subversion, ograniczając liczbę plików w katalogu do 1000. Lub przeczytaj : support.microsoft.com/kb/130694 Nie sądzę, żeby kiedykolwiek to „naprawili”, ponieważ wciąż jest to uważane za perf. usprawnienie dla NTFS.
gbjbaanb
1

Czy zdjęcie profilowe jest małe? Co powiesz na umieszczenie go w bazie danych wraz z resztą danych profilu? To może nie być najlepsza opcja dla Ciebie, ale warto rozważyć ...

Oto (starszy) oficjalny dokument Microsoft na ten temat: Do BLOBA lub nie do BLOBA .

Kyle Brandt
źródło
1

Zhakowałem małą galerię internetową, w której znalazłem odmianę tego problemu; „Tylko” miałem ~ 30 000 obrazów w katalogu pamięci podręcznej, co okazało się dość powolne (ext2 używa indeksów katalogów, jak pamiętam).

Skończyło się na zrobieniu czegoś w następujący sposób:

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

Spowoduje to podział danych na 256 katalogów, co zapewnia szybkie wyszukiwanie katalogów dla każdego z trzech poziomów.

  • Wybrałem użycie MD5 zamiast SHA-1, ponieważ MD5 gwarantuje inne wyjście, jeśli zmienisz dowolne 12 bitów po 32, więc uważam, że dobrze pasuje do haszowania nazw użytkowników, katalogów i innych krótkich rzeczy. I jest też szybki ...
  • Nie uwzględniam całego skrótu, ponieważ wygeneruje on zbyt wiele katalogów i będzie skutecznie w kółko usuwał pamięć podręczną dysku.
Morten Siebuhr
źródło
1
Można chyba użyć prostszej hash jak CRC, jak hash nie musi być silny jak kryptograficznego MD5 lub SHA ... ale różnica wydajności jest prawdopodobnie znikomy tak ...
sleske
0

Nie jest to natychmiastowa odpowiedź na twój problem, ale czymś, na co warto zwrócić uwagę w przyszłości, jest powiązany projekt OpenBSD o nazwie „Epitome”

Epitome to silnik, który zapewnia usługi przechowywania pojedynczej instancji, adresowalnej pamięci masowej oraz usługi deduplikacji.

Wszystkie twoje dane są przechowywane w magazynie danych jako bloki mieszane, usuwając nieunikalne bloki, aby zmniejszyć zużycie miejsca, i pozwala zasadniczo zapomnieć o mechanizmie przechowywania, ponieważ możesz po prostu poprosić o zawartość z magazynu danych przez UUID.

Epitome jest obecnie w fazie eksperymentalnej, ale na co należy zwrócić uwagę w przyszłości.

Muczeć
źródło
0

Zasadniczo chcesz unikać katalogów z dużą liczbą plików / katalogów. Główną przyczyną jest to, że interpretacja symboli wieloznacznych w wierszu poleceń spowoduje błędy „Zbyt wiele argumentów”, co spowoduje wiele bólu podczas próby pracy z tymi katalogami.

Poszukaj rozwiązania, które tworzy głębsze, ale węższe drzewo, np. Tworząc podfoldery, jak inni to opisali.

Thorbjørn Ravn Andersen
źródło
0

Mieliśmy podobny problem, rozwiązaniem - jak wspomniano wcześniej - jest stworzenie hierarchii katalogów.

Oczywiście, jeśli masz złożoną aplikację, która opiera się na płaskiej strukturze katalogów, prawdopodobnie będziesz potrzebować dużo łatania. Warto więc wiedzieć, że istnieje obejście tego problemu, użyj dowiązań symbolicznych, które nie mają wspomnianego limitu 32k. Masz mnóstwo czasu, aby naprawić aplikację ...

Karoly Horvath
źródło
0

Dlaczego nie zastosować metody znacznika czasu, a następnie wybrać opcję przepełnienia.

Na przykład

Powiedzmy, że twój znacznik czasu to: 1366587600

Pomiń 2 ostatnie cyfry (inaczej stanie się to trochę niedorzeczne). Podziel znaczek na zestawy 4 (liczba katalogów nie powinna przekraczać 9999 - jeśli chcesz, możesz go rozdzielić inaczej).

To powinno dać ci coś takiego:

/files/1366/5876/

Następnie sprawdź również ilość w katalogu przed przesłaniem, jeśli pobiera dużą liczbę przesłanych plików (tj. 32000 + na 100 sekund), a następnie iteruj katalog po drugiej lub liście, na przykład:

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

lub

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

Następnie zaloguj użytkownika znacznik czasu + litera lub pełny kod ścieżki do bazy danych wraz z użytkownikiem i powinieneś zostać ustawiony.

pathstamp: 1366587600 lub 13665876a (jeśli używasz liter).

To kończy się dużą liczbą katalogów, ale może być naprawdę przydatne do obsługi poprawek plików. Na przykład, jeśli użytkownik chce użyć nowego zdjęcia profilowego, nadal ma starą wersję ze znacznikiem czasu starszego, na wypadek, gdyby chciał cofnąć zmiany (nie jest to tylko nadpisanie).

Fireacer
źródło
0

Sugeruję podjęcie decyzji, ile maksymalnych podkatalogów chcesz (lub możesz) mieć w folderze nadrzędnym.

Następnie musisz przekonwertować identyfikator użytkownika, aby zaczynał się od 1.

Następnie możesz zrobić: modulo = currentId % numberOfSubdirectories

modulobędzie teraz zawierać numer podkatalogu, który nigdy nie będzie większy niż numberOfSubdirectorieszostał wybrany.

Rób co chcesz z modulo, na przykład haszuj.

Również w ten sposób podkatalogi zostaną wypełnione liniowo.

in vitro
źródło