Integración de una caché

Nota: Requisitos de versión, dependencias y estado

Se puede encontrar más sobre los requisitos de la versión, las dependencias del orden de carga de las extensiones y el estado actual en la sección de conceptos.

Los clústeres de bases de datos pueden proporcionar diferentes niveles de consistencia. A partir de PECL/mysqlnd_ms 1.2.0 es posible acosejar al complemento para que cosidere solamente los nodos del clúster que puedan proporcionar el nivel de consistencia requerido. Por ejemplo, si se usa la Replicación MySQL con su consistencia final a lo ancho del clúster, es posible solicitar la consistencia de sesión (lectura de sus escrituras) en cualquier momento usando mysqlnd_ms_set_quos(). Por favor, vea también la introducción de nivel de servicio y consistencia.

Ejemplo #1 Resumen: calidad del servicio para solicitar la lectura de sus escrituras

/* Solicitud de consistencia de sesión: lectura de sus escrituras */
     if (!mysqlnd_ms_set_qos($mysqli, MYSQLND_MS_QOS_CONSISTENCY_SESSION))
     die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));

Asumiendo que a PECL/mysqlnd se le ha indicado explícitamente que proporcione un nivel de consistencia no mayor que la consistencia final, es posible reemplazar un acceso de lectura de un nodo de la base de datos por una caché en el lado del cliente usando el tiempo de vida (TTL) como estrategia de invalidación. El nodo de la base de datos y la caché pueden o no servir datos actuales, ya que esto es lo que la consistencia final define.

El reemplazo de un acceso de lectura de un nodo de la base de datos por un acceso a la caché local puede mejorar el redimiento general y disminuir la carga de la base de datos. Si la entrada de la caché es reutilizada por otro cliente que no sea el que creó dicha entrada, se guaradará un acceso a la base de datos, por lo que se disminuye la carga de la base de datos. Además, el rendimiento del sistema se puede mejorar si el cálculo y la entrega de una consulta a la base de datos es más baja que un acceso a la caché local.

Ejemplo #2 Configuración del complemento: sin entradas especiales para la caché

{
    "myapp": {
        "master": {
            "master_0": {
                "host": "localhost",
                "socket": "\/tmp\/mysql.sock"
            }
        },
        "slave": {
            "slave_0": {
                "host": "127.0.0.1",
                "port": "3306"
            }
        },
    }
}

Ejemplo #3 Almacenar en caché una petición a un servidor

<?php
$mysqli 
= new mysqli("myapp""nombre_usuario""contraseña""base_datos");
if (!
$mysqli) {
    
/* Por supuesto, su manejo de errores es mejor... */
    
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));
}

/* Explícitamente permite la consistencia final y el almacenamiento en caché (TTL <= 60 segundos) */
if (false == mysqlnd_ms_set_qos($mysqliMYSQLND_MS_QOS_CONSISTENCY_EVENTUALMYSQLND_MS_QOS_OPTION_CACHE60)) {
    die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
}

/* Para que este ejemplo funcione, debemos esperar a que el esclavo se ponga al día. Estilo de fuerza bruta. */
$intentos 0;
do {
    
/* comprobar si el esclavo posee la tabla */
    
if ($res $mysqli->query("SELECT id FROM test")) {
        break;
    } else if (
$mysqli->errno) {
        die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
    }
    
/* esperar a que el esclavo se ponga al día */
    
usleep(200000);
} while (
$intentos++ < 10);

/* La consulta ha sido ejecutada en un esclavo, el resultado está en la caché */
assert($res);
var_dump($res->fetch_assoc());

/* Servido desde la caché */
$res $mysqli->query("SELECT id FROM test");
?>

El ejemplo muestra cómo usar la caché. Primero, se ha de establecer la calidad del servicio al de consistencia final y tener en cuenta explícitamente el almacenamiento en la caché. Esto se lleva a cabo llamando a mysqlnd_ms_set_qos(). Luego, el conjunto de resultados de cada sentencia de solo lectura se almacena en la caché hasta un máximo de segundos según lo permitido por mysqlnd_ms_set_qos().

El TTL real es menor o igual al valor establecido con mysqlnd_ms_set_qos(). El valor pasado a la función establece la edad máxima (en segundos) de los datos proporcionados. Para calcular el valor real del TTL, se comprueba la demora de replicación de un servidor y se resta del valor dado. Si, por ejemplo, la edad máxima es de 60 segundos y el esclavo notifica una demora de 10 segundos, el TTL resultante es de 50 segundos. El TTL se calcula de forma individual para cada consulta de la caché.

Ejemplo #4 Lectura de sus escrituras y almacenamiento en la caché combinados

<?php
$mysqli 
= new mysqli("myapp""nombre_usuario""contraseña""base_datos");
if (!
$mysqli) {
    
/* Por supuesto, su manejo de errores es mejor... */
    
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));
}

/* Explícitamente permite la consistencia final y el almacenamiento en caché (TTL <= 60 segundos) */
if (false == mysqlnd_ms_set_qos($mysqliMYSQLND_MS_QOS_CONSISTENCY_EVENTUALMYSQLND_MS_QOS_OPTION_CACHE60)) {
    die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
}

/* Para que este ejemplo funcione, debemos esperar a que el esclavo se ponga al día. Estilo de fuerza bruta. */
$intentos 0;
do {
    
/* comprobar si el esclavo posee la tabla */
    
if ($res $mysqli->query("SELECT id FROM test")) {
        break;
    } else if (
$mysqli->errno) {
        die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
    }
    
/* esperar a que el esclavo se ponga al día */
    
usleep(200000);
} while (
$intentos++ < 10);

assert($res);

/* La consulta ha sido ejecutada en un esclavo, el resultado está en la caché */
var_dump($res->fetch_assoc());

/* Servido desde la caché */
if (!($res $mysqli->query("SELECT id FROM test"))) {
    die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
}
var_dump($res->fetch_assoc());

/* Actualización en el maestro */
if (!$mysqli->query("UPDATE test SET id = 2")) {
    die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
}

/* Lectura de sus escrituras */
if (false == mysqlnd_ms_set_qos($mysqliMYSQLND_MS_QOS_CONSISTENCY_SESSION)) {
    die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
}

/* Obtener los últimos datos */
if (!($res $mysqli->query("SELECT id FROM test"))) {
    die(
sprintf("[%d] %s\n"$mysqli->errno$mysqli->error));
}
var_dump($res->fetch_assoc());
?>

La calidad del servicio se puede cambiar en cualquier momento para evitar el uso de la caché. Si fuera necesario, se podría cambiar para leer sus escrituras (consistencia de sesión). En este caso, la caché no se usará y se leerán datos actuales.