Trabajando con Redis en PHP

Redis es una tienda de estructura de datos de código abierto en memoria, cuyo desarrollo es patrocinado por Redis Labs. El nombre se originó en REmote DIctionary Server. Actualmente se ubica como una de las bases de datos clave-valor más populares.

Algunas de las fortalezas clave de Redis pueden resumirse de la siguiente manera:

  • Almacén de estructura de datos en memoria
  • Almacén de datos de valor clave
  • Claves con un tiempo de vida limitado
  • Publicar/suscribir mensajes
  • Se puede usar para almacenes de datos de caché
  • Transacciones
  • Replicación maestro-esclavo

Instalar Redis

Suponiendo que estamos utilizando la nueva instalación de Ubuntu 16.10 (Yakkety Yak), los siguientes pasos describen cómo podemos configurar el servidor Redis:

1-Podemos instalar el servidor Redis usando los siguientes comandos de consola:

sudo apt-get update
sudo apt-get -y install build-essential tcl
wget http://download.redis.io/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
make test
sudo make install
./src/redis-server

2-Esto debería darnos el siguiente resultado:

Configurar datos de muestra

Ejecutar el comando redis-cli en el terminal de Ubuntu nos lleva al shell interactivo de Redis. A partir de aquí, con unos simples comandos, podemos agregar los siguientes datos de muestra:

SET Key1 10
SET Key2 20
SET Key3 30
SET Key4 40
SET Key5 50

Esto debería darnos el siguiente resultado:

Usando el comando KEYS * dentro del shell redis-cli, ahora podemos enumerar todas las entradas agregadas por Redis:

Consulta a través de la extensión del controlador phpredis

Antes de comenzar a realizar consultas, debemos asegurarnos de tener instalada la CLI de PHP y la extensión del controlador phpredis:

sudo apt-get -y install php7.0-dev
sudo apt-get -y install unzip
wget https://github.com/phpredis/phpredis/archive/php7.zip -O phpredis.zip
unzip phpredis.zip
cd phpredis-php7/
phpize
./configure
make
sudo make install
echo extension=redis.so >> /etc/php/7.0/cli/php.ini

Conectando

Usando la extensión del controlador phpredis, podemos conectarnos a Redis desde PHP usando la clase Redis, de la siguiente manera:

<?php
$client = new Redis();
$client->connect('localhost', 6379);

Esta expresión de una sola línea buscará Redis en localhost bajo el puerto 6379.

Manejo de errores

La extensión del controlador phpredis lanza RedisException por cada error que ocurre usando la clase Redis. Esto facilita el manejo de errores mediante un simple bloque try…catch:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
// Code…
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

Seleccionando

Dado que Redis es un almacén de valores clave, seleccionar claves es tan fácil como usar un único método get() de la instancia de Redis:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
echo $client->get('Key3'), PHP_EOL;
echo $client->get('Key5'), PHP_EOL;
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

Esto debería darnos el siguiente resultado:

La clase de cliente Redis también proporciona el método mget(), que puede obtener más de un valor clave a la vez:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
$values = $client->mget(['Key1', 'Key2', 'Key4']);
print_r($values);
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

Esto debería darnos el siguiente resultado:

Insertar

La simplicidad detrás del mecanismo de clave-valor de Redis crea un método set() simple y directo, a través del cual insertamos nuevas entradas, como se muestra en el siguiente ejemplo:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
$client->set('user', [
'name' => 'John',
'age' => 34,
'salary' => 4200.00
]);
// $client->get('user');
// returns string containing "Array" chars
$client->set('customer', json_encode([
'name' => 'Marc',
'age' => 43,
'salary' => 3600.00
]));
// $client->get('customer');
// returns json looking string, which we can simply json_decode()
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

Esto debería darnos el siguiente resultado:

Debemos tener cuidado al usar los métodos establecidos con estructuras que no son de cadena. El valor de la clave de usuario dio como resultado que la cadena de matriz se almacenara en Redis y no en la estructura de matriz real. Esto se ordena fácilmente al convertir nuestra estructura de matriz a JSON usando json_encode(), justo antes de pasarlo al método set().
Una gran ventaja del método set() es que admite el tiempo de espera en segundos, por lo que podemos escribir fácilmente expresiones como las siguientes:

$client->set('test', 'test2', 3600);

Sin embargo, llamar al método setex() es la forma preferida para cuando queremos agregar un tiempo de espera a nuestras claves:

$client->setex('key', 3600, 'value');

Los tiempos de espera son una gran característica para usar cuando se usa Redis como base de datos de caché.
Básicamente automatizan la vida útil de la caché para nosotros.

Actualización

Actualizar un valor a través del cliente Redis es lo mismo que insertarlo. Usamos el mismo método set(), con la misma clave. El nuevo valor simplemente sobrescribe el anterior, si existe alguno:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
$client->set('test', 'test1');
$client->set('test', 'test2');
// $client->get('test');
// returns string containing "test2" chars
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

Borrando

Eliminar registros de Redis es tan fácil como llamar al método del() y pasarle la clave que queremos eliminar:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
$client->del('user');
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

Transacciones

Al igual que MongoDB, Redis tampoco tiene soporte ACID en un sentido que MySQL tiene, lo cual está realmente bien, ya que Redis es solo un almacén de clave/valor y no una base de datos relacional. Redis, sin embargo, proporciona un nivel de atomicidad. Usando MULTI, EXEC, DISCARD y WATCH, podemos ejecutar un grupo de comandos dentro de un solo paso, durante el cual Redis hace las siguientes dos garantías:

  • Nunca se puede atender otra solicitud de cliente en medio de la ejecución de nuestros comandos de grupo
  • Se procesan todos o ninguno de los comandos

Echemos un vistazo al siguiente ejemplo:

<?php
try {
$client = new Redis();
$client->connect('localhost', 6379);
$client->multi();
$result1 = $client->set('tKey1', 'Test#1'); // Valid command
$result2 = $client->zadd('tKey2', null); // Invalid command
if ($result1 == false || $result2 == false) {
$client->discard();
echo 'Transaction aborted.', PHP_EOL;
} else {
$client->exec();
echo 'Transaction commited.', PHP_EOL;
}
} catch (RedisException $e) {
echo $e->getMessage(), PHP_EOL;
}

El valor $result2 sale como falso, lo que desencadena $client->discard() ;.
Aunque, result1 es una expresión válida, vino después de la llamada $client->multi(), lo que significa que su comando no se procesa realmente; entonces, no podemos ver el valor de Test#1 almacenado en Redis. Aunque no existe un mecanismo de reversión de aspecto clásico, como teníamos con MySQL, esto lo convierte en un buen modelo de transacción.

Comparte