Optimiser les accès des modèles à la base de donnée avec Zend_Cache et APC PDF Imprimer Envoyer
Écrit par Wtc0der   
Mardi, 05 Mai 2009 00:00

Introduction

Nous avons vu dans l'article précédent comment tirer partit du cache APC pour accélérer sensiblement nos applications PHP.
Nous allons voir à présent comment appliquer ce même système de cache à nos modèles afin de réduire et d'optimiser les requêtes vers la base de donnée.

Le principe

Il faut savoir qu'a chaque instantiation de nos modèles ( = classes héritant de Zend_Db_Table_Abstract), Zend_Db
va exécuter une série de requête du style "SHOW FIELDS FROM MaTable;" afin d'en "découvrir" les champs et leurs propriétés.
C'est ce que l'on appel les méta-données (metadata en langage Zend).

Dans la pratique, il est assez rare de modifier la structure des tables sur un système en production, on peu donc facilement imaginer mettre le résultat de ces requêtes en cache.
Ça tombe bien, Zend_Db_Table_Abstract nous propose une méthode statique setDefaultMetadataCache acceptant en paramètre un objet Zend_Cache_Core.

Zend_Cache & Zend_Cache_Core


Attention

Attention, l'utilisation de cache dans une application peut-être la source d'ennuis difficile à débuguer! J'en déconseille fortement l'utilisation en environnement de développement (cf Article sur le bootstrap avancé). J'en parle en connaissance de cause... :o) Zend_Cache est suffisamment complet et complexe pour mériter un copieux article à lui tout seul, aussi je ne vais pas m'étendre sur le sujet. A minima il faut bien comprendre que Zend_Cache s'articule autour de 2 concepts : les Supports (ou backend) et les frontaux (ou ... frontend, c'était pas dur ;))

Un support (ou backend) définit le support de cache qui va être utilisé : par exemple Zend_Cache_Backend_File pour stocker le cache dans des fichiers ou Zend_Cache_Backend_Apc pour utiliser l'extension du même nom. Le choix du support doit donc se faire en fonction de plusieurs paramètres comme l'environnement, la quantité de données à mettre en cache et les performances attendues. Un dernier point : le choix du support n'a aucun lien avec l'utilisation frontal (voir plus loin), il est donc possible de changer de support à tout moment sans modifier la manière donc Zend_Cache est utilisé !

Un frontal (ou frontend) définit la façon dont on souhaite utiliser le cache : Zend_Cache_Frontend_Function pour mettre en cache un retour de fonction ou encore Zend_Cache_Core, le frontal générique permettant de créer son propre frontal à partir de ce dernier.

Mise en pratique :

» Partie 1 - Création d'une classe de cache personnalisée et adaptée à nos besoin

Afin de simplifier et de personnaliser l'utilisation du Zend_Cache, toujours dans un contexte d'environnement hétérogène, nous allons créer un composant utilisateur qui sera chargé d'implémenter le système de cache dont le backend sera fonction de la disponibilité ou non de l'extension APC sur le serveur. Si elle est présente, notre composant s'appuiera dessus sinon nous utiliserons à défaut le backend "File" (cache via le système de fichier).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
/**
* Implémentation simpifiée du Zend_Cache en fonction
* de la disponibilité ou non de l'extention APC
* Chemin : library/My/Cache.php
* @author Antoine Delaisse
* @version 2009-0.1
*/
class My_Cache {
private static $_cache = null;
private static $_lifetime = 3600;

// En cas d'utilisation du backend File
private static $_cacheDir = "/tmp/";

// Le frontal par defaut
private static $_frontal = 'Output';


// Initialise un singleton Zend_Cache
private static function init($_frontal) {

// Si aucune instance n'existe, on en initialise une
if (self::$_cache === null) {

$frontendOptions = array (
'automatic_serialization' => true,
'lifetime' => self::$_lifetime);

$backendOptions = array (
'cache_dir'=> self::$_cacheDir);

if($_frontal) {
self::$_frontal = $_frontal;
}


try {
if (extension_loaded('APC')) {
self::$_cache = Zend_Cache::factory(
self::$_frontal, 'APC',
$frontendOptions, array());
} else {
self::$_cache = Zend_Cache::factory(
self::$_frontal, 'File',
$frontendOptions, $backendOptions);
}
} catch (Zend_Cache_Exception $e) {
unset (self::$_cache);
}

if (!self::$_cache) {
throw new Zend_Exception("Aucun système de cache disponible");
}
}
}

public static function getInstance($_frontal) {
self::init($_frontal);
return self::$_cache;
}
}

» Partie 2 - Initialisation du cache et liaison avec les modèles

Nous allons réaliser l'initialisation du cache "Core" (Plus d'info sur la documentation officielle) et le paramétrage de Zend_Db_Table dans l'Initializer

Tout d'abord, ajoutons ceci au constructeur :

1
2
3






// Initilisation du système de cache.
$_CoreCache = My_Cache::getInstance('Core');
Zend_Registry::set('_CoreCache', $_CoreCache);












Enfin, modifions la fonction initDb() afin ajouter à la fin le support du cache des métadonnée si et seulement si le contexte d'exécution en cours est "PROD" (lignes 11 12 et 13):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15








public function initDb()
{
$Config = new Zend_Config_Ini($this->_root . '/application/config/config.ini', $this->_env);
$Reg = Zend_Registry::getInstance();
$Reg -> set('config', $Config);
$Reg -> set('env', $this->_env);
$temp = Zend_Db::factory($Config->db->default);
Zend_Registry::set('db', $temp);
Zend_Db_Table::setDefaultAdapter($temp);

if ($this->_env == 'PROD') {
// Si serveur de prod -> On utilise la mise en cache des metadonnées SQL
Zend_Db_Table_Abstract::setDefaultMetadataCache(Zend_Registry::get('_CoreCache'));
}
}








Conclusion :

Notre application Zend va disposer d'une double optimisation via le cache APC : Le cache d'opcode directement issu de l'installation de cette extension et le cache des méta-données utilisé par Zend_Db_Table dans une application MVC utilisant les modèles.

Comme je l'ai dis plus haut, l'utilisation de la classe Zend_Cache mériterait un article ou plusieurs articles à elle toute seule, mais nous avons vu ici qu'il est finalement assez simple à mettre en place un véritable système collaboratif entre les briques Zend_Db_Table et Zend_Cache... Merci Zend !

Mise à jour le Mercredi, 18 Novembre 2009 00:21
 

Ajouter un Commentaire


Code de sécurité
Rafraîchir