Czy można wykorzystać pulę demonów memcache do wydajniejszego udostępniania sesji?


25

Przechodzimy z konfiguracji z 1 serwerem na konfigurację z dwoma serwerami i muszę zacząć udostępniać sesje PHP między dwoma maszynami z równoważeniem obciążenia. Zainstalowaliśmy już memcache ( i uruchomiliśmy ), więc byłem mile zaskoczony, że mogłem zrealizować sesje udostępniania między nowymi serwerami, zmieniając tylko 3 linie w php.inipliku ( session.save_handler i session.save_path ):

Wymieniłem:

session.save_handler = files

z:

session.save_handler = memcache

Następnie na głównym serwerze internetowym ustawiłem session.save_pathpunkt na localhost:

session.save_path="tcp://localhost:11211"

i na serwerze podrzędnym ustawiłem session.save_pathpunkt na master:

session.save_path="tcp://192.168.0.1:11211"

Praca wykonana, przetestowałem ją i działa. Ale...

Oczywiście użycie memcache oznacza, że ​​sesje są w pamięci RAM i zostaną utracone, jeśli komputer zostanie zrestartowany lub demon memcache ulegnie awarii - trochę mnie to martwi, ale bardziej martwię się o ruch sieciowy między dwoma serwerami WWW (zwłaszcza, że skalujemy w górę), ponieważ ilekroć ktoś jest zrównoważony pod obciążeniem do serwera podrzędnego, jego sesje będą pobierane przez sieć z głównego serwera podrzędnego. Zastanawiałem się, czy mógłbym zdefiniować dwa, save_pathsaby komputery korzystały z własnej pamięci sesji przed użyciem sieci. Na przykład:

Mistrz:

session.save_path="tcp://localhost:11211, tcp://192.168.0.2:11211"

Niewolnik:

session.save_path="tcp://localhost:11211, tcp://192.168.0.1:11211"

Czy to z powodzeniem współużytkuje sesje na serwerach ORAZ poprawia wydajność? tj. oszczędzaj ruch sieciowy w 50% przypadków. Czy jest to technika tylko w przypadku przełączania awaryjnego (np. Gdy jeden demon pamięci podręcznej jest nieosiągalny)?

Uwaga : tak naprawdę nie pytam konkretnie o replikację memcache - więcej o tym, czy klient memcache PHP może osiągnąć szczyt w każdym demonie memcache w puli, zwróć sesję, jeśli ją znajdzie, i utwórz nową, jeśli nie znajdzie we wszystkich sklepach. Pisząc to, myślę, że trochę proszę od PHP, lol ...

Załóżmy : brak sesji lepkich, równoważenie obciążenia w trybie round-robin, serwery LAMP.


1
Dokumentacja Memcache nie zaleca używania Memcache do przechowywania sesji. Zobacz code.google.com/p/memcached/wiki/… !

Odpowiedzi:


37

Zastrzeżenie: Szalejesz, gdybyś mnie wysłuchał bez przeprowadzania wielu testów ORAZ uzyskania drugiej opinii od osoby wykwalifikowanej - jestem nowy w tej grze .

Pomysł poprawy wydajności zaproponowany w tym pytaniu nie zadziała. Głównym błędem, jaki popełniłem, było myślenie, że kolejność, w której sklepy memcached są zdefiniowane w puli, określa pewien priorytet. Tak nie jest . Kiedy definiujesz pulę zapamiętanych demonów (np. Używając session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"), nie wiesz, który sklep będzie używany. Dane są dystrybuowane równomiernie, co oznacza, że ​​element może być przechowywany w pierwszym lub może być ostatnim (lub może być oba, jeśli klient Memcache jest skonfigurowany do replikacji - pamiętaj, że to klient obsługuje replikację, serwer memcached robi nie rób tego sam). Tak czy inaczej oznacza, że ​​użycie localhost jako pierwszego w puli nie poprawi wydajności - istnieje 50% szans na trafienie do dowolnego sklepu.

Po przeprowadzeniu drobnych testów i badań doszedłem do wniosku, że MOŻESZ udostępniać sesje między serwerami za pomocą memcache, ALE prawdopodobnie nie chcesz - nie wydaje się być popularny, ponieważ nie skaluje się tak dobrze, jak przy użyciu udostępnionego baza danych nie jest tak niezawodna. Byłbym wdzięczny za opinie na ten temat, dzięki czemu mogę dowiedzieć się więcej ...

Zignoruj ​​następujące elementy, chyba że masz aplikację PHP:


Wskazówka 1: Jeśli chcesz udostępniać sesje na 2 serwerach za pomocą memcache:

Upewnij się, że odpowiedziałeś „ Tak ” na „ Włączyć obsługę modułu obsługi sesji memcache? ” Po zainstalowaniu klienta memcache PHP i dodać następujące /etc/php.d/memcache.inipliki:

session.save_handler = memcache

Na serwerze internetowym 1 (IP: 192.168.0.1):

session.save_path="tcp://192.168.0.1:11211"

Na serwerze internetowym 2 (IP: 192.168.0.2):

session.save_path="tcp://192.168.0.1:11211"

Wskazówka 2: Jeśli chcesz udostępniać sesje na 2 serwerach za pomocą pamięci podręcznej ORAZ mieć obsługę przełączania awaryjnego:

Dodaj następujące elementy do /etc/php.d/memcache.inipliku:

memcache.hash_strategy = consistent
memcache.allow_failover = 1

Na serwerze internetowym 1 (IP: 192.168.0.1):

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

Na serwerze internetowym 2 (IP: 192.168.0.2):

session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"

Uwagi:

  • To podkreśla kolejny błąd, który popełniłem w pierwotnym pytaniu - nie używałem identycznego session.save_pathna wszystkich serwerach.
  • W takim przypadku „przełączanie awaryjne” oznacza, że ​​w przypadku awarii jednego demona memcache klient PHP memcache zacznie korzystać z drugiego. tzn. każda osoba, której sesja w sklepie się nie powiodła, zostanie wylogowana. To nie jest przezroczysty tryb failover.

Wskazówka 3: Jeśli chcesz udostępniać sesje za pomocą pamięci podręcznej ORAZ mieć przejrzystą obsługę przełączania awaryjnego:

Taki sam jak wskazówka 2, z tą różnicą, że musisz dodać do /etc/php.d/memcache.inipliku:

memcache.session_redundancy=2

Uwagi:

  • To powoduje, że klient memcache PHP zapisuje sesje na 2 serwerach. Otrzymujesz redundancję (jak RAID-1), dzięki czemu zapisy są wysyłane do n serwerów lustrzanych, a nieudane get'spróby są ponawiane na serwerach lustrzanych. Oznacza to, że użytkownicy nie tracą sesji w przypadku awarii jednego demona memcache.
  • Zapisy lustrzane są wykonywane równolegle (przy użyciu nieblokującego IO), więc wydajność nie powinna spadać znacznie wraz ze wzrostem liczby kopii lustrzanych. Jednak ruch sieciowy wzrośnie, jeśli kopie lustrzane memcache zostaną rozprowadzone na różnych komputerach. Na przykład nie ma już 50% szans na użycie hosta lokalnego i uniknięcie dostępu do sieci.
    • Najwyraźniej opóźnienie w replikacji zapisu może spowodować, że stare dane zostaną odzyskane zamiast braku pamięci podręcznej. Pytanie brzmi, czy ma to znaczenie dla Twojej aplikacji? Jak często piszesz dane sesji?
  • memcache.session_redundancydotyczy redundancji sesji, ale istnieje również memcache.redundancyopcja ini, która może być używana przez kod aplikacji PHP, jeśli chcesz mieć inny poziom redundancji.
  • Potrzebujesz najnowszej wersji (obecnie w wersji beta ) klienta memcache PHP - Wersja 3.0.3 z pecl działała dla mnie.

Czy mógłbyś skomentować „nie skaluje się tak dobrze, jak przy użyciu wspólnej bazy danych”? Nie rozumiem, czym różni się od typowej konfiguracji DB master-slave. Dzięki!
Chłopiec Baukema,

Jest to całkiem fajny podział, choć krążą pogłoski, że nie działa to zgodnie z oczekiwaniami, gdy używasz ext/memcachewersji 3.x. Gramy również z tą opcją i postanowiłem przejrzeć listę serwerów i napisać do niej osobiście.
Do

w przypadku podpowiedzi 3: co jeśli jeden z hostów memcached ulegnie awarii, a następnie pojawi się, a następnie sekund hosta ulegnie awarii. jak rozumiem - żadne dane sesji nie zostaną przywrócone, a niektóre z nich zostaną utracone, prawda?
GioMac,

28

Odp: Wskazówka 3 powyżej (dla każdego, kto spotka się z tym za pośrednictwem google), wydaje się, że przynajmniej obecnie, aby to zadziałało, musisz użyć memcache.session_redundancy = N+1dla N serwerów w puli , przynajmniej wydaje się to minimalny próg wartość, która działa. (Testowane z php 5.3.3 na stabilnej wersji Debiana, pecl memcache 3.0.6, dwa serwery memcached session_redundancy=2uległyby awarii, jak tylko wyłączyłem pierwszy serwer w save_path, session_redundancy=3działa dobrze.)

Wygląda na to, że zostało to zarejestrowane w tych raportach błędów:


1
Nie mogę cię zalegalizować ...
fest

1
Cieszę się, że przewinąłem w dół. To był problem.
Daren Schwenke,

Nie jest dla mnie jasne, czy ta funkcja jest dostępna tylko w serii PECL memcache 3.x? Wszystkie są wymienione w oprogramowaniu Beta na stronie pecl.php.net/package/memcache , natomiast w wersji 2.2.7, jeśli zabiję serwer, na którym widzę lidera, wszystko umiera.
Joe

Szczerze mówiąc, minęły lata, odkąd na to spojrzałem. Jak pamiętam, była to funkcja 3.x (icbw). Wdrożyliśmy wiele systemów korzystających z wersji beta tej wtyczki (niektóre z nich dość duży ruch) i nie mieliśmy żadnych problemów z tym związanych. YMMV, testuj rzeczy przed ich uruchomieniem itp. :) Nie pracuję w PHP od kilku lat, więc niektóre z drobiazgów ciekawostek zaczynają zanikać.
Michael Jackson,

3

Wraz z powyższymi ustawieniami php.ini upewnij się, że ustawione są również:

memcache.allow_failover = 1  
memcache.hash_strategy = 'consistent'

Następnie uzyskasz pełne przełączenie awaryjne i redundancję po stronie klienta. Zastrzeżenie z tym podejściem polega na tym, że jeśli memcached jest wyłączony na localhost, zawsze będzie brakowało odczytu, zanim klient php memcache spróbuje następnego serwera w puli określonej w session.save_path

Pamiętaj, że wpływa to na globalne ustawienia klienta php memcache działającego na twoim serwerze internetowym.


Czy korzystanie ze consistentstrategii hashowania ma sens, biorąc pod uwagę, że session.save_pathna każdym serwerze jest inna?
Tom

1

memcached nie działa w ten sposób (popraw mnie, jeśli się mylę!)

Jeśli chcesz, aby aplikacja miała nadmiarowe miejsce do przechowywania sesji, musisz utworzyć coś, co zmieni / doda / usunie wpisy do obu zapamiętanych instancji. Memcached nie obsługuje tego, jedyne, co zapewnia, to pamięć kluczowa. Więc nie ma replikacji, synchronizacji, nic, nada.

Mam nadzieję, że się nie mylę w tej sprawie, ale to właśnie wiem o memach, które minęły kilka lat odkąd go dotknąłem.


Byłoby dla mnie przydatne, gdybyś się mylił. :-) W phpslacker.com znajduje się artykuł ( phpslacker.com/2009/03/02/php-session-clustering-with-memcache ), który sugeruje, że memcached może działać tak, jak opisano w pytaniu. Być może zależy to od tego, jak klient memcache wdraża strategię mieszania?
Tom

1
memcache tak nie działa, ale wygląda na to, że php może działać tak, jak chcesz. Będziesz musiał zmienić php.ini lub zmienić aplikację zgodnie z opisem. Z bloga: Gdzie jest klaster, o który pytasz Cóż, prawdę mówiąc, nie ma żadnych. Do tej pory mamy pulę memcache składającą się z 2 serwerów. PHP jest skonfigurowane do zapisu w puli. PHP odczytuje / zapisuje do puli serwerów w kolejności określonej przez dyrektywę ini „session.save_path”. Dla odczytów PHP zażąda obiektu pamięci podręcznej według klucza z puli. Ponieważ „przełączanie awaryjne” jest włączone, PHP będzie przeszukiwać pulę serwerów memcache jeden po drugim, aż do [...]
rozerwania

1

memcached nie replikuje się po wyjęciu z pudełka, ale repcached ( łatka memcached) tak. Jeśli jednak już używasz mysql, dlaczego po prostu nie skorzystać z jego funkcji replikacji z replikacją master-master i uzyskać korzyści z pełnej replikacji danych.

DO.


Dzięki za informację. Tak naprawdę nie szukam replikacji. Chodzi raczej o to, by po kolei sięgać do każdego memcached aż do znalezienia sesji. tzn. najpierw sprawdza localhost, ponieważ jest najszybszy, a następnie sprawdza inny serwer.
Tom

1
W imię wszystkich bogów DLACZEGO ???? To jest całkowicie niewłaściwe rozwiązanie ... cóż, prawie każdego problemu, jaki mogę wymyślić. Oprócz tego, że jest bardzo nieefektywny nawet przy zaledwie 2 serwerach, wydajność będzie się stopniowo pogarszać bardzo szybko, jeśli kiedykolwiek dodasz więcej serwerów. I to nie biorąc pod uwagę faktu, że Twoje rozwiązanie powoduje dwa razy większe prawdopodobieństwo awarii w porównaniu z pojedynczym serwerem, podczas gdy w praktyce dodanie serwerów do klastra powinno zmniejszyć prawdopodobieństwo awarii. (BTW, jeśli masz na myśli round-robin oparty na DNS, to powinowactwo sesji jest niejawne!)
symcbean

Dziękuję za opinię, tak, swobodnie przyznaję, że jestem szaleńcem w udostępnianiu sesji! :-) Jednak nadal nie rozumiem, dlaczego moja propozycja jest taka brzydka. Pomyślałem, że będzie bardziej wydajne niż używanie wspólnej bazy danych, a także pomyślałem, że zmniejszy prawdopodobieństwo awarii.
Tom

Nie, to zwiększa ich prawdopodobieństwo. Federacja danych w ten sposób ma sens, gdy masz bardzo dużą liczbę węzłów, ponieważ zmniejszasz liczbę replikacji, ale zwykle wykonujesz replikację przy określonej liczbie pul, aby zachować dostępność. Musisz być bardzo wybredny, jeśli chodzi o wydajność, aby zobaczyć różnicę między replikowaną replikacją a replikacją mysqld.
symcbean

Przetestowałem i potwierdziłem, że tak długo, jak korzystam z parametru allow_failover = 1, wiele serwerów lustrzanych sprawia, że ​​przestoje są MNIEJSZE. Mogę zamknąć jedno lustro, zrestartować je i zamknąć drugie, ponownie uruchomić i zamknąć pierwsze ponownie - wszystko to bez wylogowania. Myślę, że klient memcache PHP robi wiele sztuczek za kulisami.
Tom
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.