Der Zend-TwoLevels-Cache ist an sich eine feine Sache, da er, wie bereits beschrieben, das Schönste aus beiden Cache-Welten vereint. Diese Freude wird jedoch leider immer wieder durch manche Macken des TwoLevels-Caches getrübt.
Die Cache-Priorität wird im TwoLevels-Cache durch eine verkürzte Lebenszeit für niedrig priorisierte Cache-Einträge realisiert:
$fastLifetime = (int) ($lifetime / (11 - $priority));
Der Standardwert für die Priorität ist 8, was dazu führt, das alle Einträge standardmäßig im schnellen Cache nur mit einem Drittel der ursprünglichen Lebenszeit gespeichert werden. Damit würde der schnelle Cache nur ein Drittel der Zeit zur Verfügung stehen, danach würden alle Anfragen aus dem langsamen Cache beantwortet, bis auch dieser abgelaufen wäre und dann würde der ganze Cache neu geschrieben und das Spiel ginge von vorne los. Um diesem Problem zu begegnen und um häufig verwendete Cache-Einträge auch weiter im schnellen Cache zu halten, gibt es die Option auto_refresh_fast_cache
. Ist diese aktiviert, was in der Standard-Konfiguration der Fall ist, wird der Eintrag im schnellen Cache bei jedem load()
neu geschrieben, was fast immer zu masssiven Performance-Einbußen führt. Daher ist in diesem Fall Setzen der Priorität auf 10 für alle Einträge, wie von Fabrizio beschrieben die beste Lösung. Dadurch wird bei diesen Einträgen weder die Lebenszeit verkürzt noch werden die Einträge neu geschrieben.
Ein weiteres Problem tritt auf, wenn bei der Berechnung der $fastLifetime
durch abrunden als Ergebnis eine 0 herauskommt. Denn dann wird der Eintrag (zumindest bei APC, Memcached und XCache) für immer im Cache gespeichert. Ich habe dazu bei ZendFramework ein Issue eröffnet. Der Patch dazu verhindert zumindest das Anlegen von unbegrenzt gültigen Einträgen.
Meiner Meinung nach sollte es für die automatische Aktualisierung – genau wie für den automatic_cleaning_factor
– eine Option geben, mit der man die Häufigkeit steuern kann. Ich kann mir, außer zu Testzwecken, kein Szenario vorstellen, wo man bei jeder Leseoperation auch eine Schreiboperation erzwingen möchte. Sinnvoller wäre hier diesen Parameter analog zum automatic_cleaning_factor
mit der Trefferfrequenz auf den Cache zu justieren. Oder den Cache erst beim Unterschreiten eines Schwellenwerts der Lebenszeit neu zu schreiben. Oder die Einträge einfach ablaufen lassen und erst neu schreiben, wenn sie zum ersten Mal aus dem langsamen Cache gelesen wurden. Mit der letzten Lösung hätte man auf jeden Fall am wenigsten unnötige Schreibzugriffe, aber dafür immer mindestens einen Lesezugriff auf den langsamen Cache.
Nachtrag:
Hier noch die ZendFramework-Issues zu auto_refresh_fast_cache und dem Prioritäten- / Lifetimeproblem.
Update 18.07.2011:
Der Patch wurde mit kleinen Anpassungen angenommen und sollte in der nächsten 1.11-Version enthalten sein.
0 Kommentare