Note: Version requise, dépendances et statuts
Vous trouverez plus d'informations quant aux versions requises, à l'ordre de chargement de l'extension, et aux statuts courants dans la section relatif aux concepts !
Les clusters de base de données peuvent délivrer différents niveaux de consistences. Depuis PECL/mysqlnd_ms 1.2.0, il est possible de demander au plugin de considérer uniquement les noeuds de clusters qui peuvent délivrer le niveau de consistance requis. Par exemple, si vous utilisez un serveur de réplication MySQL asynchrone avec une échelle de cluster éventuellement consistent, il est possible de demander une session de consistence (lecture de vos écritures) à n'importe quel moment en utilisant la fonction mysqlnd_ms_set_quos(). Veuillez également vous reportez à la section de la documentation sur les niveaux de service et de consistence.
Exemple #1 Récapitulatif : qualité de service demandant de lire vos écritures
/* Demande d'une session de consistence : lecture de vos écritures */
if (!mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_SESSION))
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
Supposons que PECL/mysqlnd a été explicitement configuré pour délivrer aucun niveau de consistence plus élevé que la consistence éventuelle, il est possible de remplacer un noeud de base de données accessible en lecture avec un cache côté client utilisant time-to-live (TTL), en invalidant ainsi la statégie. Ainsi, à la fois le noeud de base de données et le cache peuvent ou non servir les données courantes, sachant que c'est ce que définit la consistence éventuelle.
Remplacer l'accès en lecture d'un noeud de base de données avec un accès au cache local peut améliorer les performances globales et baisser la charge de la base de données. Si l'entrée du cache est souvent réutilisée par d'autres clients que celui ayant créée l'entrée dans le cache, un accès base de données est sauvé et ainsi, la charge de la base de données baisse. De plus, les performances du système peuvent devenir meilleures sachant que le calcul et la délivrance d'une requête de base de données est plus lente que l'accès à un cache local.
Exemple #2 Configuration du plugin : aucune entrée spéciale pour la mise en cache
{ "myapp": { "master": { "master_0": { "host": "localhost", "socket": "\/tmp\/mysql.sock" } }, "slave": { "slave_0": { "host": "127.0.0.1", "port": "3306" } }, } }
Exemple #3 Mise en cache d'une requête esclave
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
if (!$mysqli) {
/* Bien évidemment, votre gestionnaire d'erreur est meilleur... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
}
if ( !$mysqli->query("DROP TABLE IF EXISTS test")
|| !$mysqli->query("CREATE TABLE test(id INT)")
|| !$mysqli->query("INSERT INTO test(id) VALUES (1)")
) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Autorise explicitement la consistence éventuelle et la mise en cache (TTL <= 60 secondes) */
if (false == mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_CACHE, 60)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Pour que ceci fonctionne, nous devons juste attendre d'atteindre un esclave.
Forçons le. */
$attempts = 0;
do {
/* Vérifie si l'esclave a la table */
if ($res = $mysqli->query("SELECT id FROM test")) {
break;
} else if ($mysqli->errno) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Attente d'un esclave */
usleep(200000);
} while ($attempts++ < 10);
/* La requête va être exécutée sur un esclave, le résultat est dans le cache */
assert($res);
var_dump($res->fetch_assoc());
/* Servi depuis le cache */
$res = $mysqli->query("SELECT id FROM test");
?>
Cet exemple montre la façon dont on doit utiliser la fonctionalité du cache. Tout d'abord, vous devez définir la qualité de service à une consistence éventuelle et explicitement autoriser la mise en cache. Ceci est fait en appelant la fonction mysqlnd_ms_set_qos(). Puis, le jeu de résultats de chaque requête en lecture seule est mis en cache pour plus de quelques secondes, tel qu'autorisé avec la fonction mysqlnd_ms_set_qos().
Le TTL actuel est inférieur ou égal à la valeur définie avec la fonction mysqlnd_ms_set_qos(). La valeur passée à la fonction définit l'âge maximal (en secondes) des données délivrées. Pour calculer la valeur actuelle du TTL, la latence du serveur de réplication est vérifiée et soustrait à la valeur fournie. Si, par exemple, l'âge maximal est défini à 60 secondes, et l'esclave rapporte une latence de 10 secondes, le TTL résultant sera de 50 secondes. Le TTL est calculé de façon individuelle pour chaque requête mise en cache.
Exemple #4 Lecture de vos écritures et mise en cache
<?php
$mysqli = new mysqli("myapp", "username", "password", "database");
if (!$mysqli) {
/* Bien évidemment, votre gestionnaire d'erreur est meilleur... */
die(sprintf("[%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()));
}
if ( !$mysqli->query("DROP TABLE IF EXISTS test")
|| !$mysqli->query("CREATE TABLE test(id INT)")
|| !$mysqli->query("INSERT INTO test(id) VALUES (1)")
) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Autorise explicitement la consistence éventuelle et la mise en cache (TTL <= 60 secondes) */
if (false == mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_EVENTUAL, MYSQLND_MS_QOS_OPTION_CACHE, 60)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Pour que ceci fonctionne, nous devons juste attendre d'atteindre un esclave.
Forçons le. */
$attempts = 0;
do {
/* Vérifie si l'esclave a la table */
if ($res = $mysqli->query("SELECT id FROM test")) {
break;
} else if ($mysqli->errno) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Attente d'un esclave */
usleep(200000);
} while ($attempts++ < 10);
assert($res);
/* La requête va être exécutée sur un esclave, le résultat est dans le cache */
var_dump($res->fetch_assoc());
/* Servi depuis le cache */
if (!($res = $mysqli->query("SELECT id FROM test"))) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
var_dump($res->fetch_assoc());
/* Mise à jour sur le maître */
if (!$mysqli->query("UPDATE test SET id = 2")) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Lecture de vos écritures */
if (false == mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_SESSION)) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
/* Récupération des dernières données */
if (!($res = $mysqli->query("SELECT id FROM test"))) {
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
}
var_dump($res->fetch_assoc());
?>
La qualité de service peut être modifiée à n'importe quel moment pour supprimer l'utilisation du cache. Si nécessaire, vous pouvez le modifier pour lire vos écritures (session de consistence). Dans ce cas, le cache ne sera pas utilisé et les dernières données seront lues.