Kann ein Pool von Memcache-Daemons verwendet werden, um Sitzungen effizienter zu teilen?

25

Wir wechseln von einem 1-Webserver-Setup zu einem 2-Webserver-Setup, und ich muss anfangen, PHP-Sitzungen zwischen den beiden Rechnern mit Lastenausgleich zu teilen. Wir haben memcached bereits installiert ( und gestartet ) und daher war ich angenehm überrascht, dass ich Sitzungen zwischen den neuen Servern gemeinsam nutzen konnte, indem ich nur drei Zeilen in der php.iniDatei änderte ( session.save_handler und session.save_path ):

Ich ersetzte:

session.save_handler = files

mit:

session.save_handler = memcache

Dann habe ich auf dem Master-Webserver den To- session.save_pathPoint auf localhost gesetzt:

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

und auf dem Slave-Webserver habe ich den To- session.save_pathPoint auf den Master gesetzt:

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

Arbeit erledigt, ich habe es getestet und es funktioniert. Aber...

Offensichtlich bedeutet die Verwendung von Memcache, dass sich die Sitzungen im RAM befinden und verloren gehen, wenn ein Computer neu gestartet wird oder der Memcache - Dämon abstürzt wir skalieren auf), weil immer, wenn jemand auf den Slave-Webserver geladen wird, seine Sitzungen über das Netzwerk vom Master-Webserver abgerufen werden. Ich habe mich gefragt, ob ich zwei definieren kann, save_pathsdamit die Computer in ihrem eigenen Sitzungsspeicher suchen, bevor sie das Netzwerk verwenden. Beispielsweise:

Meister:

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

Sklave:

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

Würde dies erfolgreich Sitzungen auf den Servern freigeben UND die Leistung verbessern? Das heißt, Sie sparen 50% des Netzwerkverkehrs. Oder ist diese Technik nur für Failover geeignet (z. B. wenn ein Memcache-Daemon nicht erreichbar ist)?

Hinweis : Ich frage nicht speziell nach der Memcache-Replikation - mehr darüber, ob der PHP-Memcache-Client innerhalb jedes Memcache-Daemons in einem Pool Spitzenwerte erreichen kann, eine Sitzung zurückgeben kann, wenn er eine findet, und eine neue Sitzung erstellen, wenn er keine findet in allen Geschäften. Während ich das schreibe, denke ich, dass ich ein bisschen viel von PHP verlange, lol ...

Angenommen : keine Sticky-Sessions, Round-Robin-Load-Balancing, LAMP-Server.

Tom
quelle
1
In der Memcache-Dokumentation wird die Verwendung von Memcache für die Sitzungsspeicherung nicht empfohlen. Siehe code.google.com/p/memcached/wiki/… !

Antworten:

37

Haftungsausschluss: Sie wären verrückt, wenn Sie mir zuhören würden, ohne eine Tonne Tests zu machen UND eine zweite Meinung von einer qualifizierten Person einzuholen - ich bin neu in diesem Spiel .

Die in dieser Frage vorgeschlagene Idee zur Effizienzsteigerung funktioniert nicht. Der Hauptfehler, den ich gemacht habe, war zu denken, dass die Reihenfolge, in der die zwischengespeicherten Speicher im Pool definiert sind, eine Art Priorität vorschreibt. Dies ist nicht der Fall . Wenn Sie einen Pool von Memached Daemons definieren (z. B. using session.save_path="tcp://192.168.0.1:11211, tcp://192.168.0.2:11211"), können Sie nicht wissen, welcher Speicher verwendet wird. Daten werden gleichmäßig verteilt, was bedeutet, dass ein Element möglicherweise im ersten oder im letzten gespeichert wird (oder beides, wenn der Memcache-Client für die Replikation konfiguriert ist). Beachten Sie, dass der Memcache-Server für die Replikation zuständig ist nicht selber machen). In beiden Fällen führt die Verwendung von localhost als erstem im Pool nicht zu einer Leistungsverbesserung. Es besteht eine 50% ige Chance, dass einer der beiden Stores erreicht wird.

Nachdem ich ein bisschen getestet und recherchiert habe, bin ich zu dem Schluss gekommen, dass Sie Sitzungen mithilfe von Memcache KÖNNEN, was Sie aber wahrscheinlich nicht möchten - es scheint nicht beliebt zu sein, da es nicht so gut skaliert wie eine gemeinsam genutzte Sitzung Datenbank daran ist nicht so robust. Ich würde mich über Feedback freuen, damit ich mehr erfahren kann ...

Ignorieren Sie Folgendes, sofern Sie keine PHP-App haben:


Tipp 1: Wenn Sie Sitzungen mit memcache auf zwei Servern teilen möchten:

Stellen Sie sicher, dass Sie bei der Installation des PHP-Memcache-Clients mit Ja geantwortet haben, um die Unterstützung für den Memcache-Sitzungs-Handler zu aktivieren. Fügen Sie Folgendes in Ihre /etc/php.d/memcache.iniDatei ein:

session.save_handler = memcache

Auf Webserver 1 (IP: 192.168.0.1):

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

Auf Webserver 2 (IP: 192.168.0.2):

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

Tipp 2: Wenn Sie Sitzungen mithilfe von Memcache auf zwei Servern teilen möchten UND Failover-Unterstützung haben möchten:

Fügen Sie Ihrer /etc/php.d/memcache.iniDatei Folgendes hinzu :

memcache.hash_strategy = consistent
memcache.allow_failover = 1

Auf Webserver 1 (IP: 192.168.0.1):

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

Auf Webserver 2 (IP: 192.168.0.2):

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

Anmerkungen:

  • Dies hebt einen weiteren Fehler hervor, den ich in der ursprünglichen Frage gemacht habe - ich habe nicht session.save_pathauf allen Servern einen identischen verwendet .
  • In diesem Fall bedeutet "Failover", dass der PHP-Memcache-Client bei einem Ausfall eines Memcache-Daemons den anderen verwendet. dh jeder, dessen Sitzung im Geschäft fehlgeschlagen ist, wird abgemeldet. Es ist kein transparentes Failover.

Tipp 3: Wenn Sie Sitzungen mit Memcache freigeben UND transparentes Failover unterstützen möchten:

Entspricht Tipp 2, mit der Ausnahme, dass Sie Ihrer /etc/php.d/memcache.iniDatei Folgendes hinzufügen müssen :

memcache.session_redundancy=2

Anmerkungen:

  • Dadurch schreibt der PHP-Memcache-Client die Sitzungen auf 2 Server. Sie erhalten Redundanz (wie RAID-1), sodass Schreibvorgänge an n Spiegel gesendet und fehlgeschlagene get'sSchreibvorgänge auf den Spiegeln wiederholt werden. Dies bedeutet, dass Benutzer ihre Sitzung nicht verlieren, wenn ein Memcache-Dämon ausfällt.
  • Gespiegelte Schreibvorgänge werden parallel ausgeführt (unter Verwendung von nicht blockierendem E / A), sodass die Geschwindigkeitsleistung mit zunehmender Anzahl von Spiegeln nicht stark sinken sollte. Der Netzwerkverkehr nimmt jedoch zu, wenn Ihre Memcache-Spiegel auf verschiedenen Computern verteilt sind. Beispielsweise besteht keine 50% ige Chance mehr, localhost zu verwenden und den Netzwerkzugriff zu vermeiden.
    • Anscheinend kann die Verzögerung bei der Schreibreplikation dazu führen, dass alte Daten anstelle eines Cache-Fehlschlags abgerufen werden. Die Frage ist, ob dies für Ihre Bewerbung von Bedeutung ist? Wie oft schreibst du Sitzungsdaten?
  • memcache.session_redundancydient der Sitzungsredundanz, es gibt jedoch auch eine memcache.redundancyini-Option, die von Ihrem PHP-Anwendungscode verwendet werden kann, wenn Sie eine andere Redundanzstufe wünschen.
  • Sie benötigen eine neuere Version des PHP-Memcache-Clients ( derzeit noch in der Beta ) - die Version 3.0.3 von pecl hat für mich funktioniert.
Tom
quelle
Könnten Sie einen Kommentar zu "Es skaliert nicht so gut wie eine gemeinsam genutzte Datenbank" abgeben? Ich verstehe nicht, wie es sich von einem typischen Master-Slave-DB-Setup unterscheidet. Vielen Dank!
Boy Baukema
Dies ist eine ziemlich coole Aufschlüsselung, obwohl es Gerüchte gibt (auch Fehlerberichte genannt), dass dies nicht wie erwartet funktioniert, wenn Sie ext/memcacheVersion 3.x verwenden . Wir spielen auch mit dieser Option und ich habe beschlossen, die Serverliste zu durchlaufen und selbst zu schreiben.
Bis zum
Im Fall von Tipp 3: Was passiert, wenn ein zwischengespeicherter Host ausfällt und dann hochfällt, und der zweite Host ausfällt? Soweit ich weiß, werden keine Sitzungsdaten wiederhergestellt und ein Teil geht verloren, oder?
GioMac
28

Betreff: Tipp 3 oben (für alle anderen, die zufällig über Google darauf stoßen): Damit dies funktioniert, müssen Sie derzeit mindestens memcache.session_redundancy = N+1N Server in Ihrem Pool verwenden , zumindest scheint dies der Mindestschwellenwert zu sein Wert, der funktioniert. (Getestet mit PHP 5.3.3 auf Debian Stable, pecl memcache 3.0.6, zwei Memcached - Server. session_redundancy=2Würde so schnell nicht , wie ich den ersten Server in dem ausgeschaltet save_path, session_redundancy=3funktioniert einwandfrei .)

Dies scheint in diesen Fehlerberichten festgehalten zu sein:

Michael Jackson
quelle
1
Kann dich nicht genug werben ..
Fest
1
Ich bin froh, dass ich nach unten gescrollt habe. Das war das Problem.
Daren Schwenke
Mir ist nicht klar, ob diese Funktion nur in der PECL memcache 3.x-Serie verfügbar ist. Alle diese sind in der Beta-Software unter pecl.php.net/package/memcache aufgeführt , wohingegen bei 2.2.7 alles stirbt, wenn ich den Server töte, auf dem ich den Anführer sehe.
Joe
Um ehrlich zu sein, habe ich mir das schon vor Jahren angesehen. Soweit ich mich erinnere, war es ein 3.x-Feature (icbw). Wir haben viele Systeme mit den "Beta" -Versionen dieses Plugins (von denen einige ziemlich viel Verkehr haben) bereitgestellt und hatten keine Probleme, die damit zu tun schienen. YMMV, testen Sie Dinge, bevor sie online gehen, usw. :) Ich arbeite seit ein paar Jahren nicht mehr in PHP, so dass einige der Feinheiten von Trivia allmählich verblassen.
Michael Jackson
3

Stellen Sie zusammen mit den oben gezeigten php.ini-Einstellungen sicher, dass auch Folgendes festgelegt ist:

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

Dann erhalten Sie ein vollständiges Failover und clientseitige Redundanz. Die Einschränkung bei diesem Ansatz besteht darin, dass bei einem Ausfall von memcached auf localhost immer ein Lesefehler auftritt, bevor der PHP-Memcache-Client den nächsten Server in dem in session.save_path angegebenen Pool versucht

Denken Sie daran, dass dies Auswirkungen auf die globalen Einstellungen für den PHP-Memcache-Client hat, der auf Ihrem Webserver ausgeführt wird.

Ian Lewis
quelle
Ist die Verwendung einer consistentHashing-Strategie sinnvoll, wenn man bedenkt, dass die session.save_pathauf jedem Webserver anders ist?
Tom
1

memcached funktioniert nicht so (bitte korrigiere mich wenn ich falsch liege!)

Wenn Ihre Anwendung redundanten Sitzungsspeicher haben soll, müssen Sie etwas erstellen, das Einträge in beiden zwischengespeicherten Instanzen ändert, hinzufügt oder löscht. memcached behandelt dies nicht, das einzige, was es bietet, ist der Schlüssel-Hash-Speicher. Also keine Replikation, Synchronisation, nichts, nada.

Ich hoffe, ich liege in dieser Sache nicht falsch, aber das ist, was ich von memcached kenne, ein paar Jahre, seit ich es berührt habe.

zerrissen
quelle
Es wäre praktisch für mich, wenn Sie sich irren. :-) Es gibt einen Artikel in phpslacker.com ( phpslacker.com/2009/03/02/php-session-clustering-with-memcache ), der vorschlägt, dass memcached wie in der Frage beschrieben funktionieren kann. Vielleicht hängt es davon ab, wie der Memcache-Client die Hashing-Strategie implementiert?
Tom
1
memcache funktioniert nicht so, aber es scheint, dass PHP so funktionieren kann, wie Sie es möchten. Sie müssen die php.ini oder Ihre App wie beschrieben ändern. Aus dem Blog: Wo ist das Clustering, das du fragst? Was wir bisher haben, ist ein Memcache-Pool bestehend aus 2 Servern. PHP ist so konfiguriert, dass es in den Pool schreibt. PHP liest / schreibt in den Serverpool in der durch die ini-Direktive "session.save_path" angegebenen Reihenfolge. Zum Lesen fordert PHP ein Cache-Objekt per Schlüssel aus dem Pool an. Da „Failover“ aktiviert wird PHP auf den Pool von memcache Server abfragen one-by-one , bis die [...]
tore-
1

memcached wird nicht sofort repliziert, aber repcached (ein gepatchtes memcached). Wenn Sie jedoch bereits mysql verwenden, können Sie die Replikationsfunktionalität einfach mit der Master-Master-Replikation nutzen und die Vorteile der vollständigen Datenreplikation nutzen.

C.

symcbean
quelle
Danke für die Information. Es ist nicht wirklich die Replikation, die ich anstrebe. Es ist eher so, als ob Sie in jedes Memcached der Reihe nach einen Peak einfügen möchten, bis die Sitzung gefunden ist. dh zuerst localhost überprüfen, weil es am schnellsten ist, und dann den anderen Server als nächstes überprüfen.
Tom
1
Im Namen aller Götter WARUM ???? Dies ist die völlig falsche Lösung für ... also für jedes Problem, das mir einfällt. Selbst mit nur 2 Servern ist die Leistung nicht nur sehr ineffizient, sondern verschlechtert sich auch sehr schnell, wenn Sie mehr Server hinzufügen. Dabei wird nicht berücksichtigt, dass Ihre Lösung doppelt so häufig Ausfälle verursacht wie bei einem einzelnen Server, wenn in der Praxis durch Hinzufügen von Servern zu einem Cluster die Wahrscheinlichkeit eines Ausfalls verringert wird. (Übrigens, wenn Sie DNS-basiertes Round-Robin meinen, dann ist die Sitzungsaffinität implizit!)
symcbean
Vielen Dank für das Feedback, ja, ich gebe frei zu, dass ich kein Neuling beim Teilen von Sitzungen bin! :-) Ich habe jedoch immer noch nicht verstanden, warum mein Vorschlag so hässlich ist. Ich dachte, es wäre effizienter als die Verwendung einer gemeinsam genutzten Datenbank, und ich dachte, es würde Ausfälle weniger wahrscheinlich machen.
Tom
Nein, es macht sie wahrscheinlicher. Das Zusammenführen der Daten auf diese Weise ist sinnvoll, wenn Sie über eine sehr große Anzahl von Knoten verfügen, da Sie den Replikationsaufwand verringern. In der Regel wird jedoch eine Replikation mit einer definierten Anzahl von Pools durchgeführt, um die Verfügbarkeit zu gewährleisten. Sie müssen hinsichtlich der Leistung sehr wählerisch sein, um einen Unterschied zwischen der zwischengespeicherten Replikation und der mysqld-Replikation festzustellen.
Symcbean
Ich habe getestet und bestätigt, dass mehrere Spiegel, solange ich allow_failover = 1 verwende, Ausfälle WENIGER wahrscheinlich machen. Ich kann einen Spiegel herunterfahren, ihn neu starten und den anderen herunterfahren, ihn neu starten und den ersten wieder herunterfahren - alles ohne abgemeldet zu sein. Ich schätze, der PHP-Memcache-Client macht hinter den Kulissen eine Menge Tricks.
Tom