Warum Caching mit Memcached toll ist

MySQL ist toll, denn es kann

  • Benutzerauthentifizierung mit Rechtekonzept
  • diverse Storage-Engines
  • Caching für diverse Dinge
  • verschiedene Indextypen
  • Volltextsuche
  • JOINs
  • umfangreiche Möglichkeiten der Selektion (WHERE-Bedingungen)
  • Sortierung der Daten
  • Recovery
  • Transaktionen
  • Locking

Gar nicht übel, oder?
Aber eigentlich sollte es doch um Memcached gehn. Was ist also so toll an Memcached?
Er kann von alle dem nichts und genau das ist seine Stärke:
Im Gegensatz zur (vergleichesweise langsamen) eierlegenden Wollmilchsau MySQL kann Memcached genau eine Sache: Daten (nicht persistent) speichern.
Dazu wird ein Server, der eigentliche Memcached, benötigt, auf welchen dann mit einer der zahlreichen Client-Libraries zugegriffen werden kann.
Bevor man loslegt sollte man sich zunächst über ein paar Besonderheiten klar werden:

  • Es gibt keine Zugriffskontrolle: Wer auf den Port verbinden kann, kann auch alle Daten auf dem Server lesen/schreiben – IpTables sind also Pflicht
  • Die Daten werden nur im RAM gehalten, sind also nach einem Neustart weg. Memcached ersetzt also keinesfalls eine Datenbank
  • Auf die Daten kann nur mittels eines eindeutigen Schlüssels zugegriffen werden. Iterieren ist nicht möglich
  • Die verschiedenen Client-APIs sind i.d.R. nicht kompatibel. Was man z.B. mit Perl schreibt, kann man mit PHP vermutlich nicht lesen
  • Memcached ist SCHNELL!

Sobald man das verdaut hat, kann man sich Gedanken darüber machen, wie man das nutzen kann.

Beispiel aus dem echten Leben (Der Zugriff erfolgt über PHP und mit dem prozeduralen Interface – Nähere Infos bei PHP.net):
Wir haben mehrere Millionen Gästebucheinträge von denen immer die X aktuellsten auf dem Profil des jeweiligen Benutzers angezeigt werden. Bei jedem Profilaufruf müssen also aus diesen Millionen Einträgen die Einträge des Profilbesitzer herausgesucht, chronologisch sortiert und dann ausgegeben werden. Das geht mit MySQL wunderbar, verbrät aber logischerweise einiges an Resourcen. Da Gästebücher aber wesentlich öfter gelesen, als geschrieben werden, bietet sich hier der Einsatz von Memcached an:
Beim Aufruf der Seite versucht man zunächst mittels memcache_get($connection, $gaestebuchid); die Einträge aus dem Cache zu lesen, falls das klappt ist alles bestens und man kann sie ausgeben ohne den MySQL-Server belästigen zu müssen. Werden die Einträge nicht gefunden, dann liest man die Daten ganz normal aus der Datenbank und schreibt sie anschließend mittels memcache_set($connection, $gaestebuchid, $gaestebuchArray); in den Cache, so dass sie (hoffentlich) beim nächsten Aufruf verfügbar sind. Wenn man dann noch daran denkt mittels memcache_delete($connection, $gaestebuchid); den Cacheeintrag zu löschen, wenn ein neue Eintrag hinzukommt/sich etwas ändert, dann hat man schon seinen ersten, wirkungsvollen Cachingmechanismus mittels Memcached implementiert.

Zweites Beispiel:
Um die Anzahl der eingeloggten Benutzer anzuzeigen müssen bei uns die MySQL-Tabelleneinträge der User gezählt werden, deren letzte Aktivität mehr als X Minuten zurück liegt. Da sich diese Zugriffzeit sehr häufig ändert (nämlich mit jedem Klick des Benutzers) wäre es sehr ineffizient einen Index auf die entsprechenden Spalte zu legen, was aber zu folge hat, dass MySQL jeden einzelnen Tabelleneintrag durchgehn (Table-scan) und die gespeicherte Zeit mit dem Timeout vergleichen muß, was widerrum natürlich sehr aufwändig ist.
Mit Memcached wird auch das besser: Man prüft zunächst wieder mit memcached_get ob die aktuelle Nutzerzahl schon im Cache steht, falls ja, gibt man diese aus, falls nicht muß doch wieder der MySQL-Server herhalten. Anschließend speichert man den Wert natürlich im Cache. Würde man das aber mit einem simplen memcache_set($connection, ‚onlineuser‘, $onlineuser); machen, so würde man für die komplette Laufzeit des Cache-Servers die gleiche Onlineuserzahl geliefert bekommen (weil das get jedesmal erfolgreich wäre und der SQL-Server nie mehr befragt würde). Deshalb gibt es die Möglichkeit Memcached-Einträgen einen Timeout zu verpassen. Mittels memcache_set($connection, ‚onlineuser‘, $onlineuser, 0, 60); würde dieser z.B. auf 60 Sekunden festgesetzt. Nach dieser Zeit findet man im Cache keine Onlineuserzahl mehr, so dass der SQL-Server wieder befragt wird und die Zahl sich somit minütlich erneuert.

Wie man hoffentlich deutlich erkennen kann zeigt Memcached seine Stärke nur in Verbindung mit einer Datenbank im Hintergrund. Er kann (und will) also einen Datenbankserver nicht ersetzen, aber er kann auf erstaunlich einfache Weise helfen selbigen zu entlasten.

Sollte noch jemand interessante Praxisbeispiele oder Ergänzungen haben, würde ich mich freuen darüber in den Kommentaren zu lesen.

One Response to “Warum Caching mit Memcached toll ist”

  1. Robin sagt:

    Ich Beschäftige mich zwar erst seit einigen Minuten mit dem Thema „Memcached“, doch dein Beitrag macht mir Lust auf mehr. Gerade für meine Webanwendungen ist Memcached wie geschaffen!

    Von daher, Danke für das Schmackhaft machen 🙂

Leave a Reply