Posted on 18th February 20102 Responses
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

  1. Listing w kórym jest kilkadziesiąt tysięcy pozycji zabije każdego klienta ftp, ssh i inne
  2. 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 )
  3. 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:

  1. Pytanie: Jak zsynchronizować Linuxa z serwerem NTP
  2. Pytanie: Jak zainstalować VIMa w CentOS 5
  3. Pytanie: Jak logować się przez SSH bez hasła
  4. Synchronizacja katalogów via FTP
  5. Pytanie: Jak stworzyć obraz ISO w linuxie
Comments
comment by Trexor
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));
}

comment by admin
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ę ;)

Leave a Response
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Comment moderation is enabled. Your comment may take some time to appear.