QuickCache (früher JPCache) – Vorstellung und Konfigurationsempfehlung

Vor einiger Zeit habe ich mal das Script JP Cache empfohlen. Mittlerweile wurde dieses Script unter dem neuem Namen QuickCache aktualisiert. Da ich damit bislang gute Erfahrungen gemacht habe, wollte ich es hier nochmal kurz vorstellen – und potenzielle Nutzern dieses Scripts davor bewahren einen Fehler zu begehen.

QuickCache ist ein Script, das durch Einbinden einer PHP-Datei den gesamten Output eines eurer PHP-Scripte zwischenspeichert – entweder in der Datenbank oder auf dem Dateisystem. Abhängig von der URL der Seite kann somit der Server stark entlastet werden.
Das Script schaut sich dazu die URL an, guckt dann, ob in der Datenbank ein zwischengespeichertes Dokument zu dieser URL vorhanden ist, das noch nicht abgelaufen ist (Ablaufzeit dynamisch einstellbar). Findet es eines, wird einfach das Dokument aus der Datenbank geholt und zum Client geschickt. Der restliche DB- und Server-Aufwand für die „normale Bearbeitung“ des Scripts entfällt somit.
Aufgrund der für jedes Script separat festlegbaren Ablaufzeit ist man recht flexibel: Produkt-Detailseiten eines Online-Shops ändern sich beispielswiese nicht so häufig, da könnte man einen Tag als Ablaufzeit wählen. Bei einer Startseite eines minutenaktuellen Nachrichtenportals empfiehlt sich eine sehr viel geringere Einstellung (bzw. ist fraglich, ob hier überhaupt Caching eingesetzt werden sollte).

Ganz nebenbei kümmert sich das Script dann noch um das GZIPen des Dokuments. Man kann es also bedenkenlos in jedes PHP-Script einbinden, denn auch, wenn man die Ablaufzeit des Dokuments auf -1 stellt, wird das Dokument zumindest geGZIPt (in diesem Fall aber nicht gecached). Natürlich achtet das Script dabei darauf, dass der Client das auch unterstützt (HTTP-Header Accept-Encoding).

Nun zu meinen einleitenden Worten mit dem Fehler, vor dem ich Nutzer bewahren möchte, und zum eigentlichen Sinn dieses Postings. Ich setze das Script sehr gern ein, wunderte mich aber, weshalb meine Datenbank sporadisch den Server total auslastete. In den PHPMyAdmin-Prozessen tauchten nur die normalen Abfragen auf, nur dauerten diesmal alle ca. 10 Sekunden länger. So lange wartet natürlich kein Besucher.

Also machte ich mich auf die Suche und stellte schon bald fest, dass es meine eigenen Scripte eigentlich nicht sein können – selbst die Cronjob-Scripte habe ich mir mal angesehen (um das sporadische Element zu erklären), aber auch die gingen flott durch.
Letztlich überlegte ich, welche Drittanbieter-Scripte ich laufen hatte. Zunächst fielen mir keine ein – bis ich an QuickCache dachte. Also hab ich mir da die Scripte und Einstellungen mal genauer angesehen.

Und zwar gibt es eine Einstellung $QUICKCACHE_GC, die festlegt, wie wahrscheinlich es ist, dass eine Garbage Collection durchgeführt wird. Im Klartext bedeutet das, dass Datensätze aus der Cache-Tabelle gelöscht werden, die nicht mehr gültig sind (Ablaufzeit überschritten). Der Standardwert (out-of-the-box) ist 1.
Hinzu kommt noch die Einstellung $QUICKCACHE_OPTIMIZE, die bei Aktivieren (=true) dazu führt, dass nach jeder Garbage Collection ein OPTIMIZE TABLE durchgeführt wird. Diese Einstellung ist standardmäßig aktiviert.

Bis hierhin klingt das alles prima. Die Tabelle wird ab und zu aufgeräumt und das Optimieren ist ja auch nicht verkehrt. Problematisch ist allerdings, dass bei mehreren Tausend Besuchern dieses 1 % einfach sehr häufig ist.
Eine kleine Beispielrechnung:
– 1 mal pro 100 Seitenzugriffe wird eine Garbage Collection durchgeführt.
– eine Website hat 10.000 Seitenzugriffe pro Tag
=> pro Tag wird 100 Mal ein aufwändiges DELETE-Statement ausgeführt aber noch viel schlimmer: 100 Mal pro Tag wird ein OPTIMIZE-TABLE-Statement ausgeführt! Da letzteres recht aufwändig ist, bremst das natürlich den ganzen DB-Server.

Ich schaute also mal weiter und fand folgendes komische Snippet zur Ermittlung, ob eine Zufallszahl unterhalb der Prozentgrenze liegt. Dies wird hier meines Erachtens sehr merkwürdig durchgeführt (habs bis jetzt nicht verstanden, wie das funktioniert):

if ($GLOBALS["QUICKCACHE_GC"]>0) {    
mt_srand(time(NULL));    
$precision=100000;    
// Garbagecollection probability   
 if (((mt_rand()%$precision)/$precision) <=        ($GLOBALS["QUICKCACHE_GC"]/100))    { 
     quickcache_do_gc(); 
   }
  }

Das mt_srand() ist ja eigentlich nicht mehr nötig seit PHP 4.2.0 – vermutlich wurde es aus Kompatibilitätsgründen dringelassen (welcher Webserver allerdings auf PHP<4.2 läuft, sollte sich vielleicht andere Gedanken als die über Performance machen ???? ) Gut, aber nun zu der Zufallszahlenberechnung: mt_rand() berechnet eine Zufallszahl zwischen 0 und der rechnerabhängigen Konstante MAX_RAND (seeeehr große Zahl). Und jetzt wirds für mich mystisch: Modulo die Precision und danach noch ne Division durch die gleiche Zahl. Wer das versteht, darfs mir gern mal in den Kommentaren erläutern (hab aber auch nicht weiter drüber nachgedacht, geschweige denn mir das auf Papier mal aufgeschrieben - fands einfach einen merkwürdigen Weg). Jedenfalls habe ich diesen Abschnitt lieber umgeschrieben, weil ich ihm misstraut habe, denn allein davon ist ja abhängig, wie oft die Garbage Collection durchgeführt wird. Und wenn da ein Fehler passiert, wird diese vielleicht noch viel häufiger durchgeführt als in den Konfigurationseinstellungen festgelegt. Deshalb hab ich folgendes daraus gemacht:

if(mt_rand(0,100000)/1000<$GLOBALS["QUICKCACHE_GC"]) {   
quickcache_do_gc();
  }

Normalerweise würde mt_rand(0,100) bzw. sogar mt_rand(100) ausreichen (weil die linke Grenze bei Übergabe nur eines Parameters automatisch 0 ist), aber mir war ja das 1 % von oben zu viel. Ich wollte also kleinere Werte angeben können (aber natürlich >0). Deshalb bilde ich eine größere Zufallszahl und dividiere danach, sodass am Ende eine Zufallszahl zwischen 0 und 100 mit 2 Dezimalstellen herauskommt.
Die Variable $QUICKCACHE_GC habe ich folglich auf 0.01 gesetzt. Nun wird sehr viel seltener die Garbage Collection durchgeführt und MySQL kann sich um wichtigere Dinge kümmern. Die Einstellung $QUICKCACHE_OPTIMIZE habe ich deaktiviert, da ein OPTIMIZE TABLE in meinen Augen nur sehr selten durchgeführt werden muss. Das mache ich nun per Hand 1 mal im Monat. Wem das zu bieder ist, der setzt nen Cronjob dafür ein.

Jetzt ist natürlich jegliche Update-Möglichkeit versaut, aber Updates scheint das Projekt sowieso ziemlich selten spendiert zu bekommen ???? Und zur Not kann man diese kleine Änderung bei der Zufallsberechnung auch später nochmal nachziehen.

Ich hoffe ich konnte euch QuickCache etwas näher bringen und zeigen, dass es sehr sinnvoll ist, jedoch nur, wenn es richtig eingestellt wird.
Und wer dieses Script nicht nutzen möchte, der muss ja nicht ????


Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0