Pytanie: Jak przechowywać obrazki na serwerze
Problem:
Posiadamy serwis internetowy, w którym jest bardzo duża liczba użytkowników. Zdjęcia każdego użytkownika trzymamy w osobnym folderze w katalogu /uploads. Niestety przy dużej liczbie zdjęć spada szybkość odczytu, a przy naprawde dużej system nie chce utwarzać kolejnych plików . Czy istnieje lepszy sposób przechowywania obrazków na serwerze?
Rozwiązanie:
Owszem, istnieje, ale przyjrzyjmy się przykładowi powyżej. Trzymanie ogromnej ilości katalogów w jednej lokalizacji nie jest dobrym pomysłem, a to co najmniej w dwóch powodów
- Listing w kórym jest kilkadziesiąt tysięcy pozycji zabije każdego klienta ftp, ssh i inne
- Praktycznie każda maszyna serwerowa ( mówie o linuxie ) ma nałożone ograniczenia maksymalnej liczby katalogów w jednej lokalizacji. Osobiście testowałem trzy maszyny: Centos, Debian i Slackware i na każdej to ograniczenia wynosiło 32 000 plików ( katalog to też plik )
- Jest jeszcze trzeci powód, a mianowicie odczyt przez serwer w takim gąszczu jest mniej wydajny
Co zatem moglibyśmy zrobić?
Zadajmy sobie pytanie ile katalogów w jednej lokalizacji stanowiło by dla nas optymalną liczbę? 100 ? Ale jak moglibyśmy to zrobić kiedy użytkowników mamy ponad 30 000. Istnieje bardzo proste wyjcie
Każdy użytkownik posiada swój rekord w bazie danych. Każdy rekord posiada swój unikalny klucz Primary Key w 99% przypadkach składający się z liczby typu INTEGER. Spójrzmy na przykładowe identyfikatory:
- 12
- 758
- 47255
Każdy z tych identyfikatorów przedstawiamy “płasko” w systemie plików. Zróbmy zatem tak. Załóżmy że nasz identfikator musi mieć stałą liczbę cyfr- niech to będzie 10. Przeliczmy liczbę cyfr w każdym ID i dopełnijmy go zerami żeby się zgadzało
- 0000000012
- 0000000758
- 0000047255
Założyliśmy że chcemy przechowywać maksymalnie po 100 katalogów. Czyli nasza liczba musi mieć dwa znaki ( wliczając 0-99 ). Patrząc na powyższą listę od razu nasuwa się rozwiązanie:
Weźmy każdego ID i podzielmy go wedlug jego dwóch znaków np.
- 00/00/00/00/12
- 00/00/00/07/58
- 00/00/04/72/55
Jak widzimy każda pozycja jest ścieżką względem naszego katalogu /uploads.
Spełniliśmy nasze założenie w pełni. Ograniczyliśmy liczbę katalogów w jednej lokalizacji a dodatkowo stworzyliśmy przyjazny dla serwera i siebie system plików, w którym wyszukiwanie plików nie powinno sprawiać problemów.
Poraz na mały dodatek. Żeby ostatecznie dopełnić ten post przygotowałem poniżej umieszczam oskryptowanie w php, które zajmuje się budowaniem ścieżek. Pierwotnie był tu dośc opasły skrypt składający się z dwóch funkcji, ale dzięki komentarzowi Trexora, widać jak można to samo przedstawić dużo prościej
function get_path($id, $maxlength = 10, $counterLimit = 2) { $id = str_pad( $id, $maxlength, "0", STR_PAD_LEFT ); return implode( DIRECTORY_SEPARATOR , str_split( $id, $counterLimit ) ); }
użycie:
echo get_path( 12 ); //wynik 00/00/00/00/12
Inne posty:
Posted on 2010/02/27 at 12:16
Super. Prosto i elegancko, widzę teraz, że mój przykłąd jest zrobiony nieco na około.
Dzięki za wskazówkę
Posted on 2010/02/27 at 11:58
Da się to zrealizować trochę prościej
function getPath($id, $maxlength = 10, $counterLimit = 2)
{
$id = str_pad($id, $maxlength, ‘0′, STR_PAD_LEFT);
return implode(‘/’, str_split($id, $counterLimit));
}