Partielles Caching mit KhCache¶
- Partielles Caching mit KhCache
- 1. Installation & Konfiguration
- 2. Anwendung
- 3. Beispiel
- 4. Best Practise
- 5. Datencontainer-PlugIns
Die Caching-Klasse von CodeIgniter (http://codeigniter.ch/user_guide/general/caching.html) ist sehr schnell und sehr einfach in der Bedienung. Allerdings kann mit dieser Klasse nur der komplette Output gecached werden, und auch nur dann, wenn ein View mit im Spiel ist.
Oft begegnen einem aber Situationen, in denen man nur Teile einer Seite cachen möchte (bspw. die letzten 10 Nachrichten auf einer Suchergebnisseite). Hier gibt es zahlreiche Erweiterungen, die dieses "partielle Caching" mit CI möglich machen. Beispiele hierfür sind MP_Cache (http://mpsimple.mijnpraktijk.com/mp_cache.htm) und KhCache (http://codeigniter.com/forums/viewthread/69843/) von Khaos.
Die Syntax der beiden ist sehr ähnlich, beinahe identisch. Der Unterschied liegt allerdings im Detail. Während MP_Cache etwas schneller ist (da kein md5-Hashing verwendet wird), bietet KhCache Unterstützung für eAccelerator, APC und XCache als Datencontainer.
Ich möchte euch anhand eines kleinen Beispiels die Verwendung von KhCache nahe bringen. Ziel dieses Tutorials ist es dir zu zeigen welche Funktionen KhCache bietet und wie du diese geschickt einsetzt. Nach dem Studieren dieses Tutorials kannst du:
- Datenbankabfragen cachen
- gerenderte Seiten cachen
- den Cache gezielt zu leeren.
1. Installation & Konfiguration¶
Die Installation von KhCache ist ziemlich einfach. Im Grund musst du dir nur die Library herunterladen und in folgendes Verzeichnis speichern:
(...)/application/libraries/
Ab sofort ist KhCache einsatzbereit. Du kannst allerdings noch ein paar Einstelungen vornehmen. Diese umfassen zum Beispiel den Datenspeicher (z.B. XCache, APC, File oder eAccelerator), die Gültigkeitsdauer des Cache und Optionen für die Speicherung in Dateien.
Um KhCache nun zu konfigurieren, was wie bereits gesagt optional ist, musst du im Verzeichnis
(...)/application/config/
eine Datei mit dem Namen
Khaos.php
$config['cache'] = array('container' => 'File',
'ttl' => 3600,
'File' => array('store' => BASEPATH.'cache/',
'auto_clean' => 10,
'auto_clean_life' => 3600,
'auto_clean_all' => false));
auto_clean - Standardmässig ist die Chance auf 1:10 für die Leerung des Cache eingestellt. Um diese Funktion zu deaktivieren, setze sie auf FALSE.
auto_clean_life- Dateien die älter als diese Zeitspanne (in Sekunden) sind, werden gelöscht.
auto_clean_all - Die Standardeinstellung sieht vor, dass nur Dateien mit dem Prefix "kohana_" gelöscht werden. Wenn du diesen Parameter auf TRUE setzt, werden alle Dateien aus dem Cache-Verzeichnis gelöscht.
container - File, Eaccelerator, APC, XCache (für Eaccelerator und XCache beachte bitte den Abschnitt "Datencontainer-Plugins")
Hinweis: Falls du "File" als Datencontainer angibst, muss dein angegebenes Cache-Verzeichnis mit Schreibrechten versehen sein.
Hinweis: Wie du eAccelerator auf einem eigenen Server (ded. Server/vServer) installierst kannst du auf www.serverzeit.de (http://serverzeit.de/FreeBSD/webserver-mit-apache/zend-und-eaccelerator/) nachlesen (das Tutorial ist zwar für FreeBSD (http://www.freebsd.org) geschrieben, funktioniert aber ähnlich für div. Linux-Distributionen).
2. Anwendung¶
Wenn du KhCache benutzen willst, solltest du die Library in das Autoload-Array eintragen. Es ist zwar kein Muss, ich würde es dir aber dennoch empfehlen.
KhCache bietet dir prinzipiell folgende Funktionen an:
- $this->khcache->generatekey(): Erstellt einen Identifier, den wir zum gezielten Zugriff auf den Cache benötigen.
- $this->khcache->store($key, $data, $ttl): Speichert Daten ($data) unter dem Identifier ($key) für mit einer Lebenszeit von $ttl Sekunden im Cache.
- $this->khcache->call($func, $args, $ttl): Ruft eine Funktion ($func) mit den Argumenten ($args, Typ: Array) auf und speichert den Rückgabewert für $ttl Sekunden im Cache.
- $this->khcache->fetch($key): Liest das Datenelement, der sich hinter dem Schlüssel $key versteckt aus dem Cache.
- $this->khcache->delete($key): Löscht das Datenelement mit dem Identifier $key aus dem Cache.
- $this->khcache->delete_all($key): Löscht alle Elemente aus dem Cache.
- $this->khcache->get_hits(): Gibt die Anzahl der erfolgreichen Zugriffe auf den Cache zurück (Benchmarking).
- $this->khcache->get_misses(): Gibt die Anzahl der erfolglosen Zugriffe auf den Cache zurück (Benchmarking).
3. Beispiel¶
1 /* Zunächst generieren wir uns einen Identifier ($key) */
2 $key = $this->khcache->generatekey('unique_example_identifier');
3
4 /* Ist der Rückgabewert der Funktion "fetch" mit dem angegebenen Identifier ($key) erfolglos,
5 war das angeforderte Element nicht im Cache (=== FALSE) */
6 if ( ($data = $this->khcache->fetch($key)) === FALSE )
7 {
8 $data = 'Datenelement, das gespeichert werden soll, bspw. ein Array.';
9 /* Speichere das Element $data im Cache mit $key als Identifier */
10 $this->khcache->store($key, $data);
11 }
12
13 /* Verarbeite die Daten weiter, bspw. gib den Datenstring aus. */
14 echo $data;
4. Best Practise¶
CodeIgniter bietet eine eigene Caching-Engine an, die in Sachen Performance bisher unerreicht ist. Die Nachteile wurden aber bereits im Intro erläutert. Seiten die nicht gezielt aktualisiert werden müssen, sollten mit der CI-eigenen Caching-Library optimiert werden.
Für partielles Caching hat sich gezeigt, dass es nur sinnvoll ist, dynamische Elemente bzw. Views mit dynamischem Inhalt im Cache abzulegen. Ganze Views im Cache abzulegen hat wenig Sinn, da die Seite erst serialisiert im Cache abgelegt werden und anschliessend wieder de-serialisiert werden muss. Dieser Prozess steigt linear mit der Menge der Daten an.
Geeignet für partielles Caching sind daher:
- Abfrageergebnisse,
- Rückgabewerte von Funktionen,
- (Sub-)Views mit dynamischem Inhalt,
- Besucherspezifische Daten, die dynamisch generiert werden (bspw. letztes Login-Datum),
- alles was zur Generierung eine hohe Last erzeugt, aber nicht ständig aktualisiert werden muss.
5. Datencontainer-PlugIns¶
Falls du XCache als Container nutzen willst, füge folgende Zeilen ans Ende der KhCache-Library:
1 /**
2 * Khaos :: KhCache :: XCache
3 *
4 * Wraps the XCache extension so it can be used
5 * as an KhCache Container.
6 *
7 */
8 class KH_Cache_XCache
9 {
10 /**
11 * Constructor
12 *
13 * @param array $options Container Options
14 *
15 * @return KH_Cache_XCache
16 */
17 function __construct($options)
18 {
19 // Ensure XCache is available
20 if (!extension_loaded('xcache') || !ini_get('xcache.cacher') || ini_get('xcache.var_size') == 0)
21 show_error('Khaos :: Cache :: XCache - One or more of the required XCACHE functions
22 is unavailable.');
23 }
24
25 /**
26 * Store Cache Item
27 *
28 * @param string $key
29 * @param mixed $data
30 * @param int $ttl
31 *
32 * @return bool
33 * @access public
34 */
35 function Store($key, $data, $ttl)
36 {
37 return xcache_set($key, serialize($data), $ttl);
38 }
39
40 /**
41 * Fetch Cache Item
42 *
43 * @param string $key
44 *
45 * @return mixed
46 * @access public
47 */
48 function Fetch($key)
49 {
50 return (($ret = xcache_get($key)) !== false)?unserialize($ret):false;
51 }
52
53 /**
54 * Delete Cache Item
55 *
56 * @param string $key
57 *
58 * @return bool
59 * @access public
60 */
61 function Delete($key)
62 {
63 return xcache_unset($key);
64 }
65
66 /**
67 * Delete All Cache Items
68 *
69 * @return bool
70 * @access public
71 */
72 function DeleteAll()
73 {
74 $xcache_auth = ini_get('xcache.admin.enable_auth');
75 ini_set('xcache.admin.enable_auth', 0);
76 for ($v=0; ini_get('xcache.var_count'); $v++)
77 xcache_clear_cache(XC_TYPE_VAR, $v);
78 ini_set('xcache.admin.enable_auth', $xcache_auth);
79 return true;
80 }
81 }
Für eAccelerator füge folgende Zeilen ein (Hinweis: delete_all wird nicht unterstützt):
1 // ------------------------------------------------------------------------
2
3 /**
4 * Khaos :: KhCache :: Eaccelerator
5 *
6 * Wraps the Eaccelerator extension so it can be used
7 * as an KhCache Container.
8 *
9 */
10 class KH_Cache_Eaccelerator
11 {
12 /**
13 * Constructor
14 *
15 * @param array $options Container Options
16 *
17 * @return KH_Cache_Eaccelerator
18 */
19 function KH_Cache_Eaccelerator($options)
20 {
21 // Ensure Eaccelerator is available
22 if (!function_exists('eaccelerator_put')
23 || !function_exists('eaccelerator_get')
24 || !function_exists('eaccelerator_rm'))
25 show_error('Khaos :: Cache :: Eaccelerator - One or more of the required Eaccelerator functions
26 is unavailable.');
27 }
28
29 /**
30 * Store Cache Item
31 *
32 * @param string $key
33 * @param mixed $data
34 * @param int $ttl
35 *
36 * @return bool
37 * @access public
38 */
39 function Store($key, $data, $ttl)
40 {
41 return eaccelerator_put($key, serialize($data), $ttl);
42 }
43
44 /**
45 * Fetch Cache Item
46 *
47 * @param string $key
48 *
49 * @return mixed
50 * @access public
51 */
52 function Fetch($key)
53 {
54 return (($ret = eaccelerator_get($key)) !== NULL) ? unserialize($ret) : FALSE;
55 }
56
57 /**
58 * Delete Cache Item
59 *
60 * @param string $key
61 *
62 * @return bool
63 * @access public
64 */
65 function Delete($key)
66 {
67 return eaccelerator_rm($key);
68 }
69
70 /**
71 * Delete All Cache Items
72 *
73 * @return bool
74 * @access public
75 */
76 function DeleteAll()
77 {
78 //return apc_clear_cache('user');
79 //Not available in eaccelerator
80 return FALSE;
81 }
82 }