02

FEB09

Die Welt um MemCache

Trackback URIVon Peppie in Programmierung

Jeder Web-Programmierer der an Seiten mit sehr viel Traffic (z.B. Communitys) arbeitet, kommt nicht drumrum früher oder später mit Memcache zu arbeiten. Bei uns, also ticCity, war dieser Punkt als wir etwa ~100.000 registrierte Benutzer hatten. Ich kann mich nur noch gut dran erinnern das wir etwa 300 Selects pro Sekunde auf unsere Datenbank hatten ( pro Frontend ) oO

Das Problem

Lasst uns das ganze an einem Beispiel durchgehen. Wir wollen einen MySQL-Query cachen da er 1. zu viel Ressourcen des Servers frisst und 2. relativ lange in der Ausführung dauert

1
SELECT * FROM user_tabelle;

Laut Memcache brauchen wir einen eindeutigen Schlüssel um das ganze im Speicher abzulegen, mit dem wir später dann wieder auf das Element zurückgreifen können. In unserem Fall werden die als Schlüssel den MD5-Hash aus dem Query benutzen. Unser Schlüssel würde dann wie folgt lauten:

d2c11766b5677c274b07661ba261a42e

Das Ergebnis von unserem Query legen wir dann als Objekt oder Array in Memcache ab und ordnen ihm diesen Schlüssel zu. Jedesmal wenn wir jetzt den Query ausführen können wir vorher prüfen ob es diesen Query schon im Memcache gibt und wenn ja, dann soll er den Query nicht ausführen sondern das bereits erstellte Ergebnis aus Memcache auslesen. Wenn sich jetzt z.B. ein neuer Benutzer registriert oder löscht müssen wir einfach nur diesen Schlüssel im Memcache wieder frei setzen und beim nächsten ausführen des Querys würde er neu in den Arbeitsspeicher geholt werden.

So … damit wären wir ja schon fast fertig wenn es da nicht noch ein kleines Problem gäbe, und zwar haben wir an einer anderen Stelle diese Abfrage:

1
SELECT * FROM user_tabelle WHERE geschlecht = 'm';

mit dem MD5 Key:

23c6de8b91e30d1fadd5c57d25d7d095

Da sich jetzt ein Benutzer registriert oder gelöscht hat, müssen wir natürlich auch diesen Schlüssel neu ablegen lassen.

hmmm aber wir haben oben nur den Schlüssel “d2c11766b5677c274b07661ba261a42e” gelöscht und was ist mit den anderen 100 Stellen (100 Schlüssel) die auf die “user_tabelle” zugreifen und im Cache liegen, die müssen auch gelöscht werden sonst arbeiten alle anderen auf den alten Daten.

Puh, heikle Sache :D aber so schlimm wie es sich anhört ist es garnicht, wir geben jedem Query den wir ausführen einfach einen “Namensraum”.

Mehr auf der Nächsten Seite …

Seite:
1 2

Peppie
Über den Autor:
Vor mehr als 6 Jahren habe ich mein Hobby zum Beruf gemacht. Seit her bekommt mich kein Problem so schnell in die Knie, ich bin sehr verbissen und arbeite solange an einem Problem bis es gelöst ist.

Ähnliche Artikel:

1 Kommentare

Patrick

Hallo Dennis,

bin grad eher durch Zufall auf deinen Blog gestoßen.

Ich setze mich gerade selbst mit Memcache auseinander, da es für mein Projekt wohl mehr oder weniger von essentieller Bedeutung sein wird, da wir zur Zeit ein CMS nutzen, welches – gelinde gesagt – unter aller Sau ist…

Wie dem auch sei – es ist unter Umständen besser gewisse Dinge nicht zu cachen, unter anderem ziemlich sicher die Userdaten.

Du nimmst als Beispiel die Abfrage:

SELECT * FROM user_tabelle;

woraus ich den Eindruck habe, dass du sämtliche Userregistrationsdaten zwischenspeicherst. Wir haben ebenfalls über 100.000 User im Forum registriert, entspricht etwa 20MB unkomprimierten Speicherplatz (Forum: Woltlab Burning Board). Was meinste, wie lange Memcache braucht, diese Daten wieder auszusprucken um diese für PHP verfügbar zu machen? Mehr Zeit, als eine simple DB-Abfrage bezogen auf einen speziellen User, dessen Daten du abfragen willst – dessen kannst du dir sicher sein.

Okay, nun glaube ich nicht wirklich, dass du es wirklich so machst und die gesamte User-Tabelle im Cache speicherst, das wäre in der Tat ineffektiv und etwas, nunja, dumm ums krass zu formulieren. Besser ist es, wenn du da ein anderes Beispiel für eine sinnvolle Nutzung von Memcache nutzt, wie z.B.:

Cachen von Gruppendaten und deren Zugriffsrechte
Cachen der letzten 20 News, Downloads, Artikel, die auf der Hauptseite angezeigt werden sollen
Cachen der letzten aktiven Postings der vergangenen Stunde
Cachen von CM-Systemeinstellungen

usw. Also eher kleinere Sachen, die so gut wie nie geändert werden müssen oder derer Änderungsfrequenz 30-60 Sekunden betragen darf, bevor jemandem Auffällt, dass die Daten nicht mehr stimmen können (beispiel: News können ruhig 30 sek. inkl. Kommentarzähler gecached werden, ohne dass großartig jemanden auffällt, dass statt 10 Kommentaren schon 12 vorhanden sind). Oder: Cachen von Daten, die innerhalb einer vergangenen (halben) Stunde aufgerufen wurden, da sich die User meist für solche Daten interessieren. Alles was jedoch schon sehr alt ist (also >1 Stunde) muss aus dem Cache gelöscht werden um speicherplatz frei und das System damit schneller und effizienter zu machen.

Es sind insbesondere im Falle von Systemeinstellungen und Ähnlichem Daten, die “ständig” aufgerufen und zwingend gebraucht, aber seltenst geändert werden.

Andersherum gesagt: Man sollte niemals jeden Furz zwischenspeichern, wichtig ist, dass viele ständig, wenig selten aufgerufene Daten gecached werden.

Das wird aus deinem Artikel – den ich ansonstens vollkommen okay finde – nicht deutlich.

Und im Übrigen: Es ist nicht zwingend notwendig in “Schlüsseln” per MD5 zu speichern.

Variablen werden als variable, Arrays als serialisierte Strings gespeichert. Der Name des “Schlüssels” ist dabei vollkommen frei wählbar – es dürfen auch Namen im Klartext sein (was ich zumindest definitiv bevorzuge, weil ich alleine auf dem System arbeite). Und: Sie müssen definitiv eindeutig sein, ansonsten werden vorhandene Daten schlicht überschrieben. Diese “Schlüsselvergabe” per MD5-Checksum könnte eventuell sogar im schlimmsten Falle zum Problem werden, da du auch mit verschiedenen Werten die gleichen MD5-Checksums erzeugen kannst – was zwar Zufall, aber nicht auszuschliessen ist.

Arbeitet man auf einem System mit mehreren Websites und will nicht, dass die im Cache gespeicherten Daten allen frei zugänglich sind, sollte man sich irgend ein “codewort” ausdenken, dieses md5-verschlüsseln und einem Schlüssel mit Klartextnamen voranstellen.

Beispiel:

d2c11766b5677c274b07661ba261a42e_dbquery_usertable

Das kann man zwar auch bruteforcen, aber die Aussicht auf erfolg ist recht gering, weil man in der Schlüsselvergabe sehr sehr flexibel sein kann – also auch zwei komplette md5 Schlüssel – oder in Teilen – verwenden kann…

Ich könnt noch mehr drüber schreiben, aber ich lasses mal.

Mein Fazit zu Memcache ist jedenfalls:

Speichere nur die Daten zwischen, die sehr oft gebraucht werden. Speichere sie schlau und Systemschonend und bestenfalls so, dass sie direkt an den User ohne weitere Berechnungen durch PHP weitergegeben werden können (beispielsweise BB-Codeparser VOR dem Speichern im Cache durchführen!) Erst dann ist Memcache sinnvoll nutzbar.


Kommentar schreiben

;) :( :) :D :P :o :| ^^ :> :< :cry: :S xD


Blogverzeichnis - Blog Verzeichnis bloggerei.de frisch gebloggt Blog Top Liste - by TopBlogs.de Bloggeramt.de Add to Technorati Favorites Dennis bei Xing Wikio - Top Blog UrlFan.com