Taktyki korzystania z PHP w mocno obciążonej witrynie

242

Zanim odpowiesz na to pytanie, nigdy nie opracowałem czegoś tak popularnego, aby osiągnąć wysokie obciążenie serwera. Traktuj mnie jak (westchnienie) kosmitę, który właśnie wylądował na planecie, choć taki, który zna PHP i kilka technik optymalizacji.


Rozwijam w PHP narzędzie, które może dotrzeć do całkiem dużej liczby użytkowników, jeśli zadziała. Jednakże, chociaż jestem w pełni zdolny do opracowania programu, jestem prawie nieświadomy, jeśli chodzi o tworzenie czegoś, co może poradzić sobie z dużym ruchem. Oto kilka pytań na ten temat (możesz również zamienić to pytanie w wątek dotyczący zasobów).

Bazy danych

W tej chwili planuję używać funkcji MySQLi w PHP5. Jak jednak skonfigurować bazy danych w odniesieniu do użytkowników i treści? Czy faktycznie potrzebuję wielu baz danych? W tej chwili wszystko jest pomieszane w jednej bazie danych - chociaż zastanawiałem się nad przeniesieniem danych użytkownika do jednej, faktycznej treści do innej i wreszcie zawartości strony głównej (szablonów itp.) Do innej. Moje uzasadnienie jest takie, że wysyłanie zapytań do różnych baz danych zmniejszy obciążenie, ponieważ jedna baza danych = 3 źródła ładowania. Czy to też byłoby skuteczne, gdyby wszyscy byli na tym samym serwerze?

Buforowanie

Mam system szablonów, który służy do budowania stron i wymiany zmiennych. Szablony główne są przechowywane w bazie danych i przy każdym wywołaniu szablonu wywoływana jest jego kopia w pamięci podręcznej (dokument HTML). W tej chwili mam dwa typy zmiennych w tych szablonach - var statyczny i dynamiczny var. Zmienne statyczne to zwykle rzeczy takie jak nazwy stron, nazwa strony - rzeczy, które nie zmieniają się często; dynamiczne zmienne to rzeczy, które zmieniają się przy każdym ładowaniu strony.

Moje pytanie na ten temat:

Powiedz, że mam komentarze do różnych artykułów. Co jest lepszym rozwiązaniem: przechowuj prosty szablon komentarza i wyświetlaj komentarze (z wywołania DB) za każdym razem, gdy strona jest ładowana, lub przechowuj kopię strony z komentarzami jako stronę HTML - za każdym razem, gdy komentarz jest dodawany / edytowany / usuwany strona zostanie cofnięta.

Wreszcie

Czy ktoś ma jakieś wskazówki / wskazówki dotyczące prowadzenia witryny o wysokim obciążeniu w PHP. Jestem prawie pewien, że jest to praktyczny język do użycia - Facebook i Yahoo! dać temu pierwszeństwo - ale czy są jakieś doświadczenia, na które powinienem uważać?

Ross
źródło
9
3,5 roku później i nawet nie pamiętam, nad czym pracowałem, chciałbym wiedzieć, co też uważam za tak fajne :)
Ross
8
Niech to będzie dla ciebie lekcja na temat przedwczesnej optymalizacji :)
Rimu Atkinson,

Odpowiedzi:

89

Nie ma dwóch podobnych stron. Naprawdę potrzebujesz narzędzia, takiego jak jmeter i test porównawczy, aby zobaczyć, gdzie będą Twoje problemy. Możesz spędzać dużo czasu na zgadywaniu i ulepszaniu, ale nie zobaczysz prawdziwych wyników, dopóki nie zmierzysz i nie porównasz swoich zmian.

Na przykład przez wiele lat pamięć podręczna zapytań MySQL była rozwiązaniem wszystkich naszych problemów z wydajnością. Jeśli Twoja strona działała wolno, eksperci MySQL zasugerowali włączenie bufora zapytań. Okazuje się, że jeśli masz duże obciążenie zapisu, pamięć podręczna faktycznie jest paraliżująca. Jeśli włączysz go bez testowania, nigdy się nie dowiesz.

I nie zapominaj, że nigdy nie skończyłeś skalowania. Witryna obsługująca 10req / s będzie wymagać zmian w celu obsługi 1000req / s. A jeśli masz wystarczająco dużo szczęścia, aby obsługiwać 10 000req / s, Twoja architektura prawdopodobnie będzie wyglądać zupełnie inaczej.

Bazy danych

  • Nie używaj MySQLi - PDO to „nowoczesna” warstwa dostępu do bazy danych OO. Najważniejszą funkcją do użycia są symbole zastępcze w zapytaniach. Jest wystarczająco inteligentny, aby używać przygotowań po stronie serwera i innych optymalizacji również dla Ciebie.
  • Prawdopodobnie nie chcesz w tym momencie rozbić bazy danych. Jeśli okaże się, że jedna baza danych nie tnie, istnieje kilka technik skalowania, w zależności od aplikacji. Replikacja na dodatkowe serwery zwykle działa dobrze, jeśli masz więcej odczytów niż zapisów. Sharding to technika dzielenia danych na wiele komputerów.

Buforowanie

  • Prawdopodobnie nie chcesz buforować w swojej bazie danych. Baza danych jest zwykle twoim wąskim gardłem, więc dodawanie do niej więcej IO jest zwykle złą rzeczą. Istnieje kilka pamięci podręcznych PHP, które osiągają podobne rzeczy, takie jak APC i Zend.
  • Zmierz swój system z włączaniem i wyłączaniem buforowania. Założę się, że pamięć podręczna jest cięższa niż proste wyświetlanie stron.
  • Jeśli zbudowanie komentarzy i danych artykułów z bazy danych zajmuje dużo czasu, zintegruj memcache z systemem. Możesz buforować wyniki zapytania i przechowywać je w instancji memcached. Ważne jest, aby pamiętać, że pobieranie danych z pamięci podręcznej musi być szybsze niż gromadzenie ich z bazy danych, aby uzyskać jakąkolwiek korzyść.
  • Jeśli twoje artykuły nie są dynamiczne lub masz proste dynamiczne zmiany po wygenerowaniu, rozważ zapisanie html lub php na dysku. Możesz mieć stronę index.php, która szuka na dysku artykułu, jeśli jest, przesyła go strumieniowo do klienta. Jeśli nie, generuje artykuł, zapisuje go na dysku i wysyła do klienta. Usunięcie plików z dysku spowodowałoby ponowne zapisanie stron. Jeśli komentarz zostanie dodany do artykułu, usuń kopię z pamięci podręcznej - zostanie on ponownie wygenerowany.
Gary Richardson
źródło
10
@ pisanie na dysk. Możesz nawet porzucić index.php i pozwolić Apache'owi wykonać pracę za ciebie, tak że index.php jest wywoływany tylko wtedy, gdy ścieżka nie istnieje. Używałbyś do tego mode_rewrite.
troelskn
5
-1, PDO jest znacznie wolniejszy niż MySQLi, a nawet rozszerzenie MySQL.
Alix Axel
4
PDO był znacznie wolniejszy niż mysqli i nie działał poprawnie dla zagnieżdżonych zapytań. Mysqli obsługuje również przygotowania po stronie serwera i powiązane parametry, podobnie jak PDO.
Daren Schwenke
5
Nie mogę uwierzyć, że została zaakceptowana jako odpowiedź. To nie jest bardzo dobre.
symcbean
1
about: caching - zdjęcia, css, htm i js pomogą, wyłącz też pliki cookie na obrazach!
Talvi Watia
61

Jestem głównym programistą witryny z ponad 15 milionami użytkowników. Mieliśmy bardzo mało problemów ze skalowaniem, ponieważ planowaliśmy go WCZESNIE i skalowaliśmy z namysłem. Oto niektóre ze strategii, które mogę zasugerować na podstawie mojego doświadczenia.

SCHEMAT Po pierwsze, denormalizuj swoje schematy. Oznacza to, że zamiast mieć wiele tabel relacyjnych, powinieneś zamiast tego wybrać jeden duży stół. Zasadniczo sprzężenia są marnotrawstwem cennych zasobów DB, ponieważ wykonywanie wielu przygotowań i sortowanie powoduje spalanie We / Wy dysku. Unikaj ich, kiedy możesz.

Kompromis polega na tym, że będziesz przechowywać / pobierać zbędne dane, ale jest to do przyjęcia, ponieważ przepustowość danych i wewnątrz klatki jest bardzo tania (większe dyski), podczas gdy wiele przygotowanych operacji we / wy jest o rząd wielkości droższych (więcej serwerów) .

INDEKSOWANIE Upewnij się, że twoje zapytania wykorzystują co najmniej jeden indeks. Uważaj jednak, że indeksy będą Cię kosztować, jeśli będziesz często pisać lub aktualizować. Jest kilka eksperymentalnych sztuczek, aby tego uniknąć.

Możesz spróbować dodać dodatkowe kolumny, które nie są indeksowane i które działają równolegle do indeksowanych kolumn. Następnie możesz mieć proces offline, który zapisuje nieindeksowane kolumny nad indeksowanymi kolumnami partiami. W ten sposób możesz lepiej kontrolować, kiedy mySQL będzie musiał ponownie obliczyć indeks.

Unikaj obliczonych zapytań jak zarazy. Jeśli musisz obliczyć zapytanie, spróbuj to zrobić raz na czas zapisu.

CACHING Gorąco polecam Memcached. Zostało to udowodnione przez największych graczy na stosie PHP (Facebook) i jest bardzo elastyczne. Można to zrobić na dwa sposoby, jedną z nich jest buforowanie w warstwie bazy danych, a druga buforowanie w warstwie logiki biznesowej.

Opcja warstwy DB wymagałaby buforowania wyniku zapytań pobranych z bazy danych. Możesz przesłać zapytanie SQL za pomocą md5 () i użyć go jako klucza odnośnika przed przejściem do bazy danych. Zaletą tego jest to, że jest dość łatwy do wdrożenia. Wadą (w zależności od implementacji) jest to, że tracisz elastyczność, ponieważ traktujesz to samo buforowanie w odniesieniu do wygasania pamięci podręcznej.

W sklepie, w którym pracuję, używamy buforowania warstwy biznesowej, co oznacza, że ​​każda konkretna klasa w naszym systemie kontroluje swój własny schemat buforowania i limity czasu buforowania. To działało dla nas całkiem dobrze, ale pamiętaj, że elementy pobrane z DB mogą nie być takie same jak elementy z bufora, więc będziesz musiał zaktualizować bufor i DB razem.

ODBIERANIE DANYCH Replikacja prowadzi do tej pory. Wcześniej niż się spodziewasz, Twoje zapisy staną się wąskim gardłem. Aby to zrekompensować, pamiętaj o wczesnym wspieraniu dzielenia danych. Prawdopodobnie będziesz chciał strzelić sobie później, jeśli tego nie zrobisz.

Jest dość prosty do wdrożenia. Zasadniczo chcesz oddzielić kluczowy organ od magazynu danych. Użyj globalnej bazy danych do przechowywania mapowania między kluczami głównymi i identyfikatorami klastra. Przeszukujesz to odwzorowanie, aby uzyskać klaster, a następnie odpytujesz klaster, aby uzyskać dane. Możesz buforować tę operację wyszukiwania, co sprawi, że będzie to nieistotna operacja.

Wadą tego jest to, że gromadzenie danych z wielu odłamków może być trudne. Ale możesz też to zmienić.

Przetwarzanie offline Nie zmuszaj użytkownika do czekania na backend, jeśli nie musi. Zbuduj kolejkę zadań i przenieś dowolne przetwarzanie, które możesz offline, wykonując je oddzielnie od żądania użytkownika.

mądry
źródło
9
+1 Ręce w dół, powinna to być zaakceptowana odpowiedź. Interesujące jest to, że wszystko, co kiedykolwiek czytałem o budowaniu baz danych, zawsze mówi „znormalizuj wszystkie dane w jak największym stopniu”, nie wspominając o wydajności związanej z wykonywaniem połączeń. Zawsze intuicyjnie czułem, że złączenia (szczególnie wielokrotne) dodawały dużo narzutu, ale do tej pory nie słyszałem, żeby to wyraźnie mówiono. Chciałbym lepiej zrozumieć, o czym mówiłeś, kontrolując, kiedy MySQL oblicza indeksy, to brzmi jak bardzo interesujący hack.
Evan Plaice,
Podział danych jest niezbędny w przypadku zbyt dużych baz danych. Google (firma, nie wyszukiwarka) ma wiele ciekawych rzeczy do powiedzenia na temat wdrażania schematów dzielenia. Przetwarzanie offline jest również ogromne, jeśli chodzi o ograniczenie liczby zapisów do bazy danych (i ograniczenie liczby ponownych obliczeń indeksu tabeli). Widziałem wiele blogów (i myślę, że nawet przepełnienie stosu) używa tej techniki w swoich systemach komentarzy / opinii generowanych przez użytkowników.
Evan Plaice,
1
Dziękuję za komentarze. To zadziwiające, że niektórzy argumentują za profilowaniem kodu warstwy środkowej, gdy czas wykonania VAST jest spędzany na we / wy danych lub we / wy klient-serwer. Ubber skomplikowana optymalizacja oszczędzająca 20% rabatu na czas wykonywania procesu PHP, który zajmuje 40 ms, jest bezcelowa w porównaniu do zwykłych 5% oszczędności na zapytaniu do bazy danych 1s.
thesmart
42

Pracowałem nad kilkoma stronami, które są wspierane przez PHP i MySQL w milionach odsłon / miesiąc. Oto kilka podstaw:

  1. Pamięć podręczna, pamięć podręczna, pamięć podręczna. Buforowanie jest jednym z najprostszych i najskuteczniejszych sposobów zmniejszenia obciążenia serwera WWW i bazy danych. Buforuj zawartość strony, zapytania, kosztowne obliczenia, wszystko, co jest związane z operacjami we / wy. Memcache jest bardzo prosty i skuteczny.
  2. Po osiągnięciu maksymalnego poziomu użyj wielu serwerów. Możesz mieć wiele serwerów WWW i wiele serwerów baz danych (z replikacją).
  3. Zmniejsz ogólną liczbę żądań do swoich serwerów. Wymaga to buforowania plików JS, CSS i obrazów przy użyciu nagłówków wygasających. Możesz także przenieść swoją statyczną zawartość do CDN, co przyspieszy wrażenia użytkownika.
  4. Mierz i testuj. Uruchom Nagios na swoich maszynach produkcyjnych i test obciążenia na serwerze dev / qa. Musisz wiedzieć, kiedy Twój serwer się zapali, aby temu zapobiec.

Polecam przeczytać Budowanie skalowalnych stron internetowych , zostało napisane przez jednego z inżynierów Flickr i jest świetnym źródłem informacji.

Sprawdź też mój post na blogu o skalowalności, zawiera wiele linków do prezentacji na temat skalowania z wieloma językami i platformami: http://www.ryandoherty.net/2008/07/13/unicorns-and-scalability/

Ryan Doherty
źródło
1
+1 Jest tutaj wiele dobrych informacji. Ostatnio badam więcej na ten temat, a twoja odpowiedź jest zgodna ze wszystkim, co przeczytałem. Pamięć podręczna, buforowanie, CDN dla zawartości statycznej, ograniczenie żądań; wszystkie dobre rzeczy. Dodałbym również, generuję skróty na statycznych plikach zawartości (jeśli masz CDN / pamięć podręczną) po stronie serwera, aby zaktualizowane pliki miały unikatowy podpis w pamięci podręcznej. Łącz również statyczne pliki źródłowe (css, javascript) w locie (i buforuj je za pomocą skrótów nazw plików), aby ograniczyć żądania. Ponadto, generuj kciuki dynamicznie (i przechowuj je w pamięci podręcznej)
Evan Plaice
Google stworzył moduł apache o nazwie mod_pagespeed, który może obsługiwać wszystkie konkatenacje plików, minimalizację, zmianę nazw plików w celu uwzględnienia skrótu itp. Dla całej zawartości statycznej. Powinno to na początku dodać tylko niewielki narzut przetwarzania na serwery, dopóki pamięci podręczne (i CDN) nie zostaną zapełnione większością treści. Ponadto ze względów bezpieczeństwa generalnie złym pomysłem jest umieszczanie tabel, które są publicznie dostępne (użytkownicy) w tej samej bazie danych, co tabele, niż obsługa zaplecza (jeśli z jakiegoś powodu jedna z tabel zostanie zhakowana).
Evan Plaice,
39

Odp: PDO / MySQLi / MySQLND

@ gary

Nie można po prostu powiedzieć „nie używaj MySQLi”, ponieważ mają one inne cele. PDO jest prawie jak warstwa abstrakcji (chociaż tak naprawdę nie jest) i ma na celu ułatwienie korzystania z wielu produktów bazodanowych, podczas gdy MySQLi jest specyficzny dla kolekcji MySQL. Błędem jest twierdzenie, że PDO jest nowoczesną warstwą dostępu w kontekście porównywania jej z MySQLi, ponieważ twoje stwierdzenie sugeruje, że postęp był mysql -> mysqli -> PDO, co nie jest prawdą.

Wybór między MySQLi i PDO jest prosty - jeśli chcesz obsługiwać wiele produktów bazodanowych, korzystaj z PDO. Jeśli używasz tylko MySQL, możesz wybrać między PDO a MySQLi.

Dlaczego więc miałbyś wybrać MySQLi zamiast PDO? Zobacz poniżej ...

@ross

Masz rację co do MySQLnd, który jest najnowszą biblioteką na poziomie podstawowego języka MySQL, jednak nie zastępuje MySQLi. MySQLi (podobnie jak PDO) pozostaje sposobem interakcji z MySQL za pomocą kodu PHP. Oba używają libmysql jako klienta C stojącego za kodem PHP. Problem polega na tym, że libmysql znajduje się poza głównym silnikiem PHP i właśnie tam wchodzi mysqlnd, tj. Jest to natywny sterownik, który wykorzystuje podstawowe elementy wewnętrzne PHP w celu maksymalizacji wydajności, szczególnie w przypadku wykorzystania pamięci.

MySQLnd jest rozwijany przez samych MySQL i niedawno wylądował w gałęzi PHP 5.3, która jest w trakcie testów RC, gotowych do wydania jeszcze w tym roku. Będziesz wtedy mógł używać MySQLnd z MySQLi ... ale nie z PDO. To da MySQLi wzrost wydajności w wielu obszarach (nie we wszystkich) i sprawi, że będzie najlepszym wyborem do interakcji MySQL, jeśli nie potrzebujesz abstrakcyjnych możliwości PDO.

To powiedziawszy, MySQLnd jest teraz dostępny w PHP 5.3 dla PDO, więc możesz uzyskać korzyści z ulepszeń wydajności od ND do PDO, jednak PDO jest nadal ogólną warstwą bazy danych i dlatego nie będzie w stanie czerpać z niego tak dużych korzyści ulepszenia w ND jak MySQLi .

Niektóre przydatne testy porównawcze można znaleźć tutaj, chociaż pochodzą one z 2006 roku. Trzeba także pamiętać o takich rzeczach, jak ta opcja .

Przy podejmowaniu decyzji między MySQLi a PDO należy wziąć pod uwagę wiele czynników. W rzeczywistości nie będzie to miało znaczenia, dopóki nie dojdziesz do wyjątkowo wysokich liczb żądań, w takim przypadku bardziej sensowne jest użycie rozszerzenia, które zostało specjalnie zaprojektowane dla MySQL, niż takiego, które wyodrębnia rzeczy i zapewnia sterownik MySQL .

Nie jest to prosta kwestia, która z nich jest najlepsza, ponieważ każda z nich ma zalety i wady. Musisz przeczytać linki, które podałem i wymyślić własną decyzję, a następnie przetestować ją i się dowiedzieć. Używałem PDO w poprzednich projektach i jest to dobre rozszerzenie, ale moim wyborem dla czystej wydajności będzie MySQLi z nową skompilowaną opcją MySQLND (po wydaniu PHP 5.3).

davidmytton
źródło
6
Zmieniłem PDO na mysqli i regularne zapytania zaczęły się wykonywać dokładnie 2 razy szybciej.
serg
5
@serg: chcesz opublikować kilka testów, aby to potwierdzić ?, ponieważ poważnie wątpię, że po prostu przejście z PDO na mysqli dałoby ci taki wzrost prędkości.
Stann
23

Generał

  • Nie próbuj optymalizować, zanim zaczniesz widzieć rzeczywiste obciążenie świata. Możesz zgadywać, ale jeśli nie, zmarnowałeś swój czas.
  • Zastosowanie jmeter , xdebug lub innym narzędziem do benchmarku miejsce.
  • Jeśli ładowanie zaczyna być problemem, prawdopodobnie dotyczy to buforowania obiektów lub danych, więc ogólnie czytaj o opcjach buforowania (memcached, MySQL caching options)

Kod

  • Profiluj swój kod, abyś wiedział, gdzie jest wąskie gardło i czy znajduje się w kodzie, czy w bazie danych

Bazy danych

  • Użyj MYSQLi, jeśli przenośność do innych baz danych nie jest istotna, PDO przeciwnym razie
  • Jeśli testy porównawcze ujawniają, że problem stanowi baza danych, sprawdź zapytania przed rozpoczęciem buforowania. Użyj EXPLAIN, aby zobaczyć, gdzie spowalniają twoje zapytania.
  • Po zoptymalizowaniu zapytań i buforowaniu bazy danych w jakiś sposób możesz użyć wielu baz danych. Replikacja na wiele serwerów lub dzielenie na fragmenty (dzielenie danych na wiele baz danych / serwerów) może być właściwe, w zależności od danych, zapytań i rodzaju zachowania odczytu / zapisu.

Buforowanie

  • Dużo pisania poświęcono buforowaniu kodu, obiektów i danych. Wyszukaj artykuły na temat APC , Zend Optimizer , memcached , QuickCache , JPCache . Zrób to trochę, zanim naprawdę będziesz musiał, a będziesz mniej zaniepokojony rozpoczęciem niezoptymalizowanego.
  • APC i Zend Optimizer to pamięci podręczne opcode, które przyspieszają kod PHP, unikając ponownej analizy i ponownej kompilacji kodu. Generalnie prosty w instalacji, warto zrobić wcześnie.
  • Memcached to ogólna pamięć podręczna, której można używać do buforowania zapytań, funkcji lub obiektów PHP lub całych stron. Kod musi być specjalnie napisany, aby go użyć, co może być zaangażowanym procesem, jeśli nie ma centralnych punktów do obsługi tworzenia, aktualizacji i usuwania buforowanych obiektów.
  • QuickCache i JPCache to pamięci podręczne plików, w przeciwnym razie podobne do Memcached. Podstawowa koncepcja jest prosta, ale wymaga także kodu i jest łatwiejsza dzięki centralnym punktom tworzenia, aktualizacji i usuwania.

Różne

  • Rozważ alternatywne serwery WWW dla dużego obciążenia. Serwery takie jak lighthttp i nginx mogą obsługiwać duże ilości ruchu w dużo mniejszej pamięci niż Apache , jeśli możesz poświęcić moc i elastyczność Apache (lub jeśli po prostu nie potrzebujesz tych rzeczy, których często nie potrzebujesz).
  • Pamiętaj, że sprzęt jest obecnie zaskakująco tani, więc nie zapomnij o wysiłku, aby zoptymalizować duży blok kodu w porównaniu do „kupmy serwer potworów”.
  • Rozważ dodanie do tego pytania tagów „MySQL” i „skalowanie”
Paul Kroll
źródło
9

APC jest absolutną koniecznością. To nie tylko świetny system buforowania, ale zysk z automatycznie buforowanych plików PHP jest darem niebios. Jeśli chodzi o koncepcję wielu baz danych, nie sądzę, byś wiele skorzystał z posiadania różnych baz danych na tym samym serwerze. Może to trochę przyspieszyć w czasie kwerendy, ale wątpię, czy wysiłek włożony we wdrożenie i utrzymanie kodu dla wszystkich trzech, przy jednoczesnym upewnieniu się, że są zsynchronizowane, byłby tego wart.

Polecam także uruchomienie Xdebug, aby znaleźć wąskie gardła w twoim programie. Sprawiło, że optymalizacja była dla mnie bardzo prosta.

tslocum
źródło
9

Po pierwsze, jak myślę Knuth, „przedwczesna optymalizacja jest źródłem wszelkiego zła”. Jeśli nie musisz teraz zajmować się tymi problemami, nie rób tego, najpierw skoncentruj się na dostarczeniu czegoś, co działa poprawnie. Biorąc to pod uwagę, jeśli optymalizacje nie mogą się doczekać.

Spróbuj profilować zapytania do bazy danych, dowiedzieć się, co jest wolne, a co dużo, i opracuj strategię optymalizacji.

Chciałbym zbadać Memcached ponieważ wiele witryn o wyższym obciążeniu używa do efektywnego buforowania zawartości wszystkich typów, a interfejs obiektu PHP jest całkiem niezły.

Podział baz danych między serwery i zastosowanie pewnego rodzaju techniki równoważenia obciążenia (np. Wygenerowanie losowej liczby między 1 a # redundantną bazą danych z niezbędnymi danymi - i użycie tej liczby do ustalenia, z którym serwerem bazy danych się połączyć) może być również doskonałym sposobem na zwiększenie wydajność.

Wszystkie te działały w przeszłości całkiem dobrze w przypadku niektórych witryn o wysokim obciążeniu. Mam nadzieję, że to pomoże Ci zacząć :-)

Eric Scrivner
źródło
1
RequiredFullQuote: „Powinniśmy zapomnieć o małej wydajności, powiedzmy w około 97% przypadków: przedwczesna optymalizacja jest źródłem wszelkiego zła”
Alister Bulman
RequiredReallyFullQuote: „Programiści tracą ogromną ilość czasu na myślenie lub martwienie się o szybkość niekrytycznych części swoich programów, a te próby wydajności mają silny negatywny wpływ przy rozważaniu debugowania i konserwacji. Powinniśmy zapomnieć o małej wydajności, powiedzmy w 97% przypadków: przedwczesna optymalizacja jest źródłem wszelkiego zła. Jednak nie powinniśmy tracić naszych możliwości w tak krytycznych 3%. ”
cHao
6

Profilowanie aplikacji za pomocą Xdebug (jak zalecana tj9991) na pewno będzie koniecznością. Optymalizacja rzeczy na ślepo nie ma większego sensu. Xdebug pomoże Ci znaleźć prawdziwe wąskie gardła w kodzie, dzięki czemu możesz mądrze spędzić czas optymalizacji i naprawić fragmenty kodu, które faktycznie powodują spowolnienia.

Jeśli używasz Apache, innym narzędziem, które może pomóc w testowaniu, jest Siege . Pomoże Ci przewidzieć, w jaki sposób Twój serwer i aplikacja zareagują na duże obciążenia, naprawdę sprawdzając, jak działa.

Każdy rodzaj pamięci podręcznej opcodu dla PHP (jak APC lub jeden z wielu innych) również bardzo pomoże.

Bob Somers
źródło
6

Prowadzę stronę internetową z 7-8 milionami odsłon miesięcznie. Niezbyt dużo, ale na tyle, że nasz serwer poczuł obciążenie. Wybrane przez nas rozwiązanie było proste: Memcache na poziomie bazy danych. To rozwiązanie działa dobrze, jeśli głównym problemem jest ładowanie bazy danych.

Zaczęliśmy od używania Memcache do buforowania całych obiektów i najczęściej używanych wyników bazy danych. Działało, ale wprowadzało również błędy (moglibyśmy uniknąć niektórych z nich, gdybyśmy byli bardziej ostrożni).

Więc zmieniliśmy nasze podejście. Zbudowaliśmy opakowanie bazy danych (dokładnie tymi samymi metodami, co nasza stara baza danych, więc łatwo było je zmienić), a następnie podklasowaliśmy go, aby zapewnić metody dostępu do bazy danych memcached.

Teraz wystarczy zdecydować, czy zapytanie może wykorzystywać wyniki zapisane w pamięci podręcznej (i być może nieaktualne), czy nie. Większość zapytań uruchamianych przez użytkowników jest teraz pobierana bezpośrednio z Memcache. Wyjątkiem są aktualizacje i wstawki, które na głównej stronie internetowej zdarzają się tylko z powodu logowania. Ten dość prosty sposób zmniejszył obciążenie naszego serwera o około 80%.

Vegard Larsen
źródło
6

Co jest warte, buforowanie jest DIRT SIMPLE w PHP, nawet bez pakietu rozszerzenia / pomocnika, takiego jak memcached.

Wszystko, co musisz zrobić, to utworzyć bufor wyjściowy za pomocą ob_start().

Utwórz globalną funkcję pamięci podręcznej. Połączenieob_start , przekaż funkcję jako oddzwanianie. W funkcji wyszukaj wersję strony w pamięci podręcznej. Jeśli istnieje, podaj go i zakończ.

Jeśli nie istnieje, skrypt będzie kontynuował przetwarzanie. Kiedy osiągnie pasujące ob_end (), wywoła podaną funkcję. W tym momencie po prostu dostajesz zawartość bufora wyjściowego, upuszczasz je do pliku, zapisujesz plik i kończysz.

Dodaj część wygasania / wyrzucania elementów bezużytecznych.

I wiele osób nie zdaje sobie sprawy, że możesz zagnieździć ob_start()/ ob_end()dzwonić. Więc jeśli już używasz bufora wyjściowego do, na przykład, parsowania reklam lub wykonywania podświetlania składni, czy cokolwiek innego, możesz po prostu zagnieździć kolejne ob_start/ob_endpołączenie.

AJ
źródło
+1, ponieważ wygląda na ciekawy pomysł. Nie wiem, jak dobrze działa pod względem wydajności
Sylverdrag
+1, ponieważ jest to ciekawy pomysł. Te oddzwaniania mogą nazywać mnie moją klasą buforowania!
Xeoncross,
5

Dzięki za porady dotyczące rozszerzeń buforowania PHP - czy możesz wyjaśnić powody używania jednego nad drugim? Słyszałem wspaniałe rzeczy o memcachowanych przez IRC, ale nigdy nie słyszałem o APC - jakie są wasze opinie na ich temat? Zakładam, że używanie wielu systemów buforowania jest dość przeciwne do zamierzonych.

W rzeczywistości wielu używa APC i memcached razem ...

ceejayoz
źródło
4

Wygląda na to, że się myliłem . MySQLi jest wciąż rozwijany. Ale zgodnie z artykułem zespół PDS_MySQL jest obecnie wspierany przez zespół MySQL. Z artykułu:

Ulepszone rozszerzenie MySQL - mysqli - jest flagowym produktem. Obsługuje wszystkie funkcje serwera MySQL, w tym zestawy znaków, przygotowane instrukcje i przechowywane procedury. Sterownik oferuje hybrydowy interfejs API: możesz użyć proceduralnego lub obiektowego stylu programowania w zależności od preferencji. mysqli zawiera PHP 5 i nowsze wersje. Pamiętaj, że koniec życia PHP 4 to 2008-08-08.

Obiekty danych PHP (PDO) to warstwa abstrakcji dostępu do bazy danych. PDO pozwala używać tych samych wywołań API dla różnych baz danych. PDO nie oferuje żadnego stopnia abstrakcji SQL. PDO_MYSQL to sterownik MySQL dla PDO. PDO_MYSQL jest dostarczany z PHP 5. Począwszy od PHP 5.3 Programiści MySQL aktywnie się do tego przyczyniają. Korzyści z PDO związane ze zunifikowanym interfejsem API są oferowane w cenie, w której funkcje specyficzne dla MySQL, na przykład wiele instrukcji, nie są w pełni obsługiwane przez zunifikowane API.

Przestań używać pierwszego sterownika MySQL dla PHP, jaki kiedykolwiek opublikowano: ext / mysql. Od czasu wprowadzenia MySQL Improved Extension - mysqli - w 2004 z PHP 5, nie ma powodu, aby nadal używać najstarszego sterownika. ext / mysql nie obsługuje zestawów znaków, przygotowanych instrukcji i procedur przechowywanych. Jest ograniczony do zestawu funkcji MySQL 4.0. Uwaga: Rozszerzona obsługa MySQL 4.0 kończy się w 31.12.2008. Nie ograniczaj się do zestawu funkcji takiego starego oprogramowania! Uaktualnij do mysqli, zobacz także Converting_to_MySQLi. Z naszego punktu widzenia mysql jest w trybie tylko serwisowym.

Wydaje mi się, że artykuł jest stronniczy w stosunku do MySQLi. Przypuszczam, że jestem stronniczy w stosunku do PDO. Naprawdę lubię PDO nad MySQLi. To dla mnie proste. Interfejs API jest znacznie bliższy innym językom, które zaprogramowałem. Interfejsy OO wydają się działać lepiej.

Nie spotkałem żadnych konkretnych funkcji MySQL, które nie byłyby dostępne za pośrednictwem PDO. Byłbym zaskoczony, gdybym to zrobił.

Gary Richardson
źródło
3

PDO jest również bardzo wolny, a jego API jest dość skomplikowane. Nikt w ich zdrowych zmysłach nie powinien go używać, jeśli przenośność nie stanowi problemu. I spójrzmy prawdzie w oczy, w 99% wszystkich aplikacji internetowych tak nie jest. Po prostu trzymasz się MySQL lub PostrgreSQL lub cokolwiek, nad czym pracujesz.

Jeśli chodzi o pytanie PHP i co wziąć pod uwagę. Myślę, że przedwczesna optymalizacja jest źródłem wszelkiego zła. ;) Najpierw załóż aplikację, postaraj się utrzymać ją w czystości, jeśli chodzi o programowanie, zrób trochę dokumentacji i napisz testy jednostkowe. W związku z powyższym nie będzie problemów z refaktoryzacją kodu, gdy przyjdzie czas. Ale najpierw chcesz to zrobić i wypchnąć, aby zobaczyć, jak ludzie reagują na to.

Do
źródło
2

Pewny pdo jest ładny, ale nie ma już pewne kontrowersje o jego wydajności w porównaniu do mysql i mysqli, chociaż wydaje się teraz naprawić.

Powinieneś użyć pdo, jeśli przewidujesz przenośność, ale jeśli nie, mysqli powinno być dobrym rozwiązaniem. Ma interfejs OO, przygotowane instrukcje i większość tego, co oferuje pdo (oprócz, no cóż, przenośności).

Dodatkowo, jeśli wydajność jest naprawdę potrzebna, przygotuj się na (natywny mysql) sterownik MysqLnd w PHP 5.3, który będzie znacznie ściślej zintegrowany z php, z lepszą wydajnością i lepszym wykorzystaniem pamięci (i statystykami dostrajania wydajności).

Pamięć podręczna jest dobra, jeśli masz klastry serwerów (i ładowanie podobne do YouTube), ale najpierw wypróbuję APC .

Berzemus
źródło
2

Podano już wiele dobrych odpowiedzi, ale chciałbym wskazać alternatywną pamięć podręczną opcode o nazwie XCache . Tworzy go świetny współpracownik.

Ponadto, jeśli w przyszłości może być konieczne równoważenie obciążenia serwera bazy danych, serwer proxy MySQL może bardzo pomóc w osiągnięciu tego celu.

Oba te narzędzia powinny dość łatwo podłączyć się do istniejącej aplikacji, więc optymalizację można przeprowadzić, gdy jest to potrzebne, bez nadmiernego wysiłku.

hangy
źródło
2

Pierwsze pytanie brzmi: jak naprawdę tego oczekujesz? A ile planujesz zainwestować w swoją infrastrukturę. Ponieważ czujesz potrzebę zadania pytania tutaj, domyślam się, że spodziewasz się zacząć od małego z ograniczonym budżetem.

Wydajność nie ma znaczenia, jeśli witryna nie jest dostępna. A dla dostępności potrzebujesz skalowania poziomego. Minimum, z którego można rozsądnie uciec, to 2 serwery, oba z uruchomionym apache, php i mysql. Skonfiguruj jeden DBMS jako slave do drugiego. Wykonuj wszystkie zapisy na wzorcu i wszystkie odczyty w lokalnej bazie danych (cokolwiek to jest) - chyba że z jakiegoś powodu musisz ponownie odczytać właśnie odczytane dane (użyj wzorca). Upewnij się, że masz maszynę do automatycznego promowania niewolnika i ogrodzenia mistrza. Użyj DNS w trybie round-robin dla adresów serwera WWW, aby zwiększyć powinowactwo do węzła slave.

Partycjonowanie danych między różnymi węzłami bazy danych na tym etapie jest bardzo złym pomysłem - możesz jednak rozważyć podzielenie ich na różne bazy danych na tym samym serwerze (co ułatwi partycjonowanie między węzłami po przejęciu Facebooka).

Upewnij się, że masz narzędzia do monitorowania i analizy danych, aby mierzyć wydajność witryn i identyfikować wąskie gardła. Większość problemów z wydajnością można naprawić, pisząc lepsze SQL / naprawiając schemat bazy danych.

Przechowywanie pamięci podręcznej szablonów w bazie danych to głupi pomysł - baza danych powinna stanowić centralne wspólne repozytorium danych strukturalnych. Zachowaj pamięć podręczną szablonów w lokalnym systemie plików na swoich serwerach WWW - będzie ona dostępna szybciej i nie spowolni dostępu do bazy danych.

Używaj pamięci podręcznej kodu operacyjnego.

Poświęć dużo czasu na studiowanie witryny i dzienników, aby zrozumieć, dlaczego działa tak wolno.

Wciśnij jak najwięcej buforowania na klienta.

Użyj mod_gzip, aby skompresować wszystko, co możesz.

DO.

symcbean
źródło
2

Moją pierwszą radą jest przemyślenie tego problemu i wzięcie go pod uwagę przy projektowaniu witryny, ale nie przesadzaj . Często trudno jest przewidzieć sukces nowej witryny, a ja lepiej poświęcę swój czas na wczesne wstawanie i optymalizowanie go później.

Ogólnie rzecz biorąc, Simple jest szybki . Szablony spowalniają. Bazy danych spowalniają. Skomplikowane biblioteki spowalniają cię. Nakładanie szablonów na siebie, pobieranie ich z baz danych i analizowanie w złożonej bibliotece -> opóźnienia czasowe mnożą się ze sobą.

Po uruchomieniu podstawowej witryny uruchom testy, aby pokazać, gdzie spędzić wysiłek. Trudno zobaczyć, gdzie celować. Często, aby przyspieszyć, będziesz musiał rozwikłać złożoność kodu, co czyni go większym i trudniejszym do utrzymania, więc chcesz to zrobić tylko w razie potrzeby.

Z mojego doświadczenia wynika, że ​​połączenie z bazą danych było stosunkowo drogie. Jeśli możesz sobie z tym poradzić, nie łącz się z bazą danych dla odwiedzających na najczęściej odwiedzanych stronach, takich jak strona główna witryny. Tworzenie wielu połączeń z bazą danych jest szaleństwem z bardzo niewielką korzyścią.

lod
źródło
1

@ Gary

Nie używaj MySQLi - PDO to „nowoczesna” warstwa dostępu do bazy danych OO. Najważniejszą funkcją do użycia są symbole zastępcze w zapytaniach. Jest wystarczająco inteligentny, aby używać przygotowań po stronie serwera i innych optymalizacji również dla Ciebie.

W tej chwili pracuję nad PDO i wygląda na to, że masz rację - jednak wiem, że MySQL rozwija rozszerzenie MySQLd dla PHP - myślę, że odniesie sukces albo MySQL, albo MySQLi - co o tym sądzisz?


@ Ryan , Eric , tj9991

Dzięki za porady dotyczące rozszerzeń buforowania PHP - czy możesz wyjaśnić powody używania jednego nad drugim? Słyszałem wspaniałe rzeczy o memcachowanych przez IRC, ale nigdy nie słyszałem o APC - jakie są wasze opinie na ich temat? Zakładam, że używanie wielu systemów buforowania jest dość przeciwne do zamierzonych.

Na pewno będę sortować testerów profilujących - bardzo dziękuję za twoje rekomendacje na ich temat.

Ross
źródło
1

W najbliższym czasie nie widzę, żebym przestawiał się z MySQL - więc chyba nie potrzebuję możliwości abstrakcji PDO. Dzięki za artykuły DavidM, bardzo mi pomogły.

Ross
źródło
1

Zajrzyj do mod_cache , wyjściowej pamięci podręcznej dla serwera WWW Apache, która przypomina buforowanie wyjściowe w ASP.NET.

Tak, widzę, że wciąż jest eksperymentalna, ale kiedyś będzie ostateczna.

Andrei Rînea
źródło
1

Nie mogę uwierzyć, że nikt jeszcze o tym nie wspominał: modularyzacja i abstrakcja. Jeśli uważasz, że Twoja witryna będzie musiała przerodzić się w wiele maszyn, musisz go zaprojektować tak, to możliwe! To oznacza głupie rzeczy, takie jak nie zakładanie, że baza danych znajduje się na localhost. Oznacza to również rzeczy, które na początku będą kłopotliwe, takie jak pisanie warstwy abstrakcji bazy danych (np. PDO, ale o wiele lżejsze, ponieważ robi tylko to, czego potrzebujesz).

A to oznacza takie rzeczy, jak praca z ramami. Będziesz potrzebować warstw do swojego kodu, abyś mógł później zwiększyć wydajność poprzez refaktoryzację warstwy abstrakcji danych, na przykład poprzez nauczenie, że niektóre obiekty znajdują się w innej bazie danych - a kod nie musi wiedzieć ani się tym przejmować .

Na koniec uważaj na operacje wymagające dużej ilości pamięci, na przykład niepotrzebne kopiowanie ciągów. Jeśli możesz zmniejszyć zużycie pamięci PHP, zyskasz większą wydajność ze swojego serwera i jest to coś, co można skalować, gdy przejdziesz do rozwiązania z równoważeniem obciążenia.

staticsan
źródło
1

Jeśli pracujesz z dużą ilością danych, a buforowanie ich nie wycina, zajrzyj do Sfinksa. Osiągnęliśmy świetne wyniki przy użyciu SphinxSearch nie tylko do lepszego wyszukiwania tekstu, ale także jako zamiennika pobierania danych dla MySQL przy przetwarzaniu większych tabel. Jeśli użyjesz SphinxSE (wtyczki MySQL), przekroczył on nasz wzrost wydajności, jaki uzyskaliśmy po kilkakrotnym buforowaniu, a implementacja aplikacji jest niezła.


źródło
1

Punkty dotyczące pamięci podręcznej są natychmiastowe; jest to najmniej skomplikowana i najważniejsza część budowania wydajnej aplikacji. Chciałbym dodać, że chociaż memcached jest świetny, APC jest około pięć razy szybszy, jeśli twoja aplikacja żyje na jednym serwerze.

Artykuł „Porównanie wydajności pamięci podręcznej” na blogu wydajności MySQL zawiera kilka ciekawych testów porównawczych na ten temat - http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/ .

Johannes Gorset
źródło