Un cliente Redis flexible y con todas las funciones para PHP 7.2 y versiones posteriores.
Se pueden encontrar más detalles sobre este proyecto en las preguntas frecuentes.
EVALSHA
o EVAL
.SCAN
, SSCAN
, ZSCAN
y HSCAN
(Redis >= 2.8) basada en iteradores de PHP.Esta biblioteca se puede encontrar en Packagist para una gestión más sencilla de las dependencias de los proyectos utilizando Composer. Los archivos comprimidos de cada versión están disponibles en GitHub.
composer require predis/predis
Predis se basa en las funciones de carga automática de PHP para cargar sus archivos cuando sea necesario y cumple con el estándar PSR-4. La carga automática se maneja automáticamente cuando las dependencias se administran a través de Composer, pero también es posible aprovechar su propio cargador automático en proyectos o scripts que carecen de función de carga automática:
// Prepend a base path if Predis is not available in your "include_path".
require ' Predis/Autoloader.php ' ;
Predis Autoloader:: register ();
Al crear una instancia de cliente sin pasar ningún parámetro de conexión, Predis asume 127.0.0.1
y 6379
como host y puerto predeterminados. El tiempo de espera predeterminado para la operación connect()
es de 5 segundos:
$ client = new Predis Client ();
$ client -> set ( ' foo ' , ' bar ' );
$ value = $ client -> get ( ' foo ' );
Los parámetros de conexión se pueden proporcionar en forma de cadenas URI o matrices con nombre. Esta última es la forma preferida de proporcionar parámetros, pero las cadenas URI pueden ser útiles cuando los parámetros se leen desde fuentes no estructuradas o parcialmente estructuradas:
// Parameters passed using a named array:
$ client = new Predis Client ([
' scheme ' => ' tcp ' ,
' host ' => ' 10.0.0.1 ' ,
' port ' => 6379 ,
]);
// Same set of parameters, passed using an URI string:
$ client = new Predis Client ( ' tcp://10.0.0.1:6379 ' );
Se puede acceder a los servidores protegidos con contraseña agregando password
a los parámetros establecidos. Cuando las ACL están habilitadas en Redis >= 6.0, se requieren tanto username
como password
para la autenticación del usuario.
También es posible conectarse a instancias locales de Redis usando sockets de dominio UNIX, en este caso los parámetros deben usar el esquema unix
y especificar una ruta para el archivo de socket:
$ client = new Predis Client ([ ' scheme ' => ' unix ' , ' path ' => ' /path/to/redis.sock ' ]);
$ client = new Predis Client ( ' unix:/path/to/redis.sock ' );
El cliente puede aprovechar el cifrado TLS/SSL para conectarse a instancias remotas seguras de Redis sin la necesidad de configurar un proxy SSL como stunnel. Esto puede resultar útil al conectarse a nodos que se ejecutan en varios proveedores de alojamiento en la nube. El cifrado se puede habilitar usando el esquema tls
y una variedad de opciones adecuadas pasadas a través del parámetro ssl
:
// Named array of connection parameters:
$ client = new Predis Client ([
' scheme ' => ' tls ' ,
' ssl ' => [ ' cafile ' => ' private.pem ' , ' verify_peer ' => true ],
]);
// Same set of parameters, but using an URI string:
$ client = new Predis Client ( ' tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1 ' );
Los esquemas de conexión redis
(alias de tcp
) y rediss
(alias de tls
) también son compatibles, con la diferencia de que las cadenas de URI que contienen estos esquemas se analizan siguiendo las reglas descritas en sus respectivos documentos de registro provisional de la IANA.
La lista real de parámetros de conexión admitidos puede variar dependiendo de cada backend de conexión, por lo que se recomienda consultar su documentación o implementación específica para obtener más detalles.
Predis puede agregar múltiples conexiones al proporcionar una serie de parámetros de conexión y la opción adecuada para indicar al cliente cómo agregarlos (agrupación, replicación o una lógica de agregación personalizada). Las matrices con nombre y las cadenas de URI se pueden combinar al proporcionar configuraciones para cada nodo:
$ client = new Predis Client ([
' tcp://10.0.0.1?alias=first-node ' , [ ' host ' => ' 10.0.0.2 ' , ' alias ' => ' second-node ' ],
], [
' cluster ' => ' predis ' ,
]);
Consulte la sección de conexiones agregadas de este documento para obtener más detalles.
Las conexiones a Redis son diferidas, lo que significa que el cliente se conecta a un servidor solo cuando es necesario. Si bien se recomienda dejar que el cliente haga sus propias cosas bajo el capó, puede haber ocasiones en las que todavía se desee tener control de cuándo se abre o cierra la conexión: esto se puede lograr fácilmente invocando $client->connect()
y $client->disconnect()
. Tenga en cuenta que el efecto de estos métodos en las conexiones agregadas puede diferir según cada implementación específica.
Se pueden configurar muchos aspectos y comportamientos del cliente pasando opciones específicas del cliente al segundo argumento de PredisClient::__construct()
:
$ client = new Predis Client ( $ parameters , [ ' prefix ' => ' sample: ' ]);
Las opciones se administran mediante un contenedor similar a un mini DI y sus valores se pueden inicializar de forma diferida solo cuando sea necesario. Las opciones de cliente admitidas de forma predeterminada en Predis son:
prefix
: cadena de prefijo aplicada a cada clave encontrada en los comandos.exceptions
: si el cliente debe generar o devolver respuestas ante errores de Redis.connections
: lista de backends de conexión o una instancia de fábrica de conexiones.cluster
: especifica un backend de cluster ( predis
, redis
o invocable).replication
: especifica un backend de replicación ( predis
, sentinel
o invocable).aggregate
: configura el cliente con una conexión agregada personalizada (invocable).parameters
: lista de parámetros de conexión predeterminados para conexiones agregadas.commands
: especifica una instancia de fábrica de comandos para usar a través de la biblioteca.Los usuarios también pueden proporcionar opciones personalizadas con valores u objetos invocables (para inicialización diferida) que se almacenan en el contenedor de opciones para su uso posterior a través de la biblioteca.
Las conexiones agregadas son la base sobre la cual Predis implementa la agrupación y la replicación y se utilizan para agrupar múltiples conexiones a nodos únicos de Redis y ocultar la lógica específica necesaria para manejarlas adecuadamente según el contexto. Las conexiones agregadas generalmente requieren una serie de parámetros de conexión junto con la opción de cliente adecuada al crear una nueva instancia de cliente.
Predis se puede configurar para que funcione en modo de agrupación en clústeres con un enfoque tradicional de fragmentación del lado del cliente para crear un grupo de nodos independientes y distribuir el espacio de claves entre ellos. Este enfoque necesita algún tipo de monitoreo externo del estado de los nodos y requiere que el espacio de claves se reequilibre manualmente cuando se agregan o eliminan nodos:
$ parameters = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' cluster ' => ' predis ' ];
$ client = new Predis Client ( $ parameters );
Junto con Redis 3.0, se introdujo un nuevo tipo de agrupación supervisada y coordinada en forma de redis-cluster. Este tipo de enfoque utiliza un algoritmo diferente para distribuir los espacios de claves, con los nodos de Redis coordinándose mediante la comunicación a través de un protocolo de chismes para manejar el estado de salud, el reequilibrio, el descubrimiento de nodos y la redirección de solicitudes. Para conectarse a un clúster administrado por redis-cluster, el cliente requiere una lista de sus nodos (no necesariamente completa ya que descubrirá automáticamente nuevos nodos si es necesario) y las opciones del cliente cluster
configuradas en redis
:
$ parameters = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' cluster ' => ' redis ' ];
$ client = new Predis Client ( $ parameters , $ options );
El cliente se puede configurar para operar en una configuración de maestro único/esclavos múltiples para proporcionar una mejor disponibilidad del servicio. Cuando se utiliza la replicación, Predis reconoce comandos de solo lectura y los envía a un esclavo aleatorio para proporcionar algún tipo de equilibrio de carga y cambia al maestro tan pronto como detecta un comando que realiza cualquier tipo de operación que terminaría modificando el espacio de claves o el valor de una clave. En lugar de generar un error de conexión cuando falla un esclavo, el cliente intenta recurrir a un esclavo diferente entre los proporcionados en la configuración.
La configuración básica necesaria para usar el cliente en modo de replicación requiere que un servidor Redis sea identificado como maestro (esto se puede hacer a través de parámetros de conexión configurando el parámetro role
en master
) y uno o más esclavos (en este caso, configurando role
como slave
. para esclavos es opcional):
$ parameters = [ ' tcp://10.0.0.1?role=master ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' replication ' => ' predis ' ];
$ client = new Predis Client ( $ parameters , $ options );
La configuración anterior tiene una lista estática de servidores y depende completamente de la lógica del cliente, pero es posible confiar en redis-sentinel
para un entorno HA más sólido con servidores centinela que actúan como fuente de autoridad para los clientes para el descubrimiento de servicios. La configuración mínima requerida por el cliente para trabajar con redis-sentinel es una lista de parámetros de conexión que apuntan a un grupo de instancias de centinela, la opción replication
configurada en sentinel
y la opción service
configurada con el nombre del servicio:
$ sentinels = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' replication ' => ' sentinel ' , ' service ' => ' mymaster ' ];
$ client = new Predis Client ( $ sentinels , $ options );
Si los nodos maestro y esclavo están configurados para requerir una autenticación de los clientes, se debe proporcionar una contraseña a través de la opción de cliente parameters
globales. Esta opción también se puede utilizar para especificar un índice de base de datos diferente. La matriz de opciones del cliente se vería así:
$ options = [
' replication ' => ' sentinel ' ,
' service ' => ' mymaster ' ,
' parameters ' => [
' password ' => $ secretpassword ,
' database ' => 10 ,
],
];
Si bien Predis puede distinguir los comandos que realizan operaciones de escritura y de solo lectura, EVAL
y EVALSHA
representan un caso de esquina en el que el cliente cambia al nodo maestro porque no puede saber cuándo es seguro ejecutar un script Lua en los esclavos. Si bien este es de hecho el comportamiento predeterminado, cuando ciertos scripts de Lua no realizan operaciones de escritura, es posible proporcionar una pista para indicarle al cliente que siga con los esclavos para su ejecución:
$ parameters = [ ' tcp://10.0.0.1?role=master ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' replication ' => function () {
// Set scripts that won't trigger a switch from a slave to the master node.
$ strategy = new Predis Replication ReplicationStrategy ();
$ strategy -> setScriptReadOnly ( $ LUA_SCRIPT );
return new Predis Connection Replication MasterSlaveReplication ( $ strategy );
}];
$ client = new Predis Client ( $ parameters , $ options );
$ client -> eval ( $ LUA_SCRIPT , 0 ); // Sticks to slave using `eval`...
$ client -> evalsha ( sha1 ( $ LUA_SCRIPT ), 0 ); // ... and `evalsha`, too.
El directorio examples
contiene algunos scripts que demuestran cómo se puede configurar y utilizar el cliente para aprovechar la replicación en escenarios tanto básicos como complejos.
La canalización puede ayudar con el rendimiento cuando es necesario enviar muchos comandos a un servidor al reducir la latencia introducida por los tiempos de ida y vuelta de la red. La canalización también funciona con conexiones agregadas. El cliente puede ejecutar la canalización dentro de un bloque invocable o devolver una instancia de canalización con la capacidad de encadenar comandos gracias a su interfaz fluida:
// Executes a pipeline inside the given callable block:
$ responses = $ client -> pipeline ( function ( $ pipe ) {
for ( $ i = 0 ; $ i < 1000 ; $ i ++) {
$ pipe -> set ( " key: $ i " , str_pad ( $ i , 4 , ' 0 ' , 0 ));
$ pipe -> get ( " key: $ i " );
}
});
// Returns a pipeline that can be chained thanks to its fluent interface:
$ responses = $ client -> pipeline ()-> set ( ' foo ' , ' bar ' )-> get ( ' foo ' )-> execute ();
El cliente proporciona una abstracción para transacciones de Redis basadas en MULTI
y EXEC
con una interfaz similar a las canalizaciones de comandos:
// Executes a transaction inside the given callable block:
$ responses = $ client -> transaction ( function ( $ tx ) {
$ tx -> set ( ' foo ' , ' bar ' );
$ tx -> get ( ' foo ' );
});
// Returns a transaction that can be chained thanks to its fluent interface:
$ responses = $ client -> transaction ()-> set ( ' foo ' , ' bar ' )-> get ( ' foo ' )-> execute ();
Esta abstracción puede realizar operaciones de verificación y configuración gracias a WATCH
y UNWATCH
y proporciona reintentos automáticos de transacciones canceladas por Redis cuando se tocan las teclas WATCH
ed. Para ver un ejemplo de una transacción usando CAS, puede ver el siguiente ejemplo.
Si bien intentamos actualizar Predis para mantenernos actualizados con todos los comandos disponibles en Redis, es posible que prefiera seguir con una versión anterior de la biblioteca o proporcionar una forma diferente de filtrar argumentos o analizar respuestas para comandos específicos. Para lograrlo, Predis brinda la capacidad de implementar nuevas clases de comandos para definir o anular comandos en la fábrica de comandos predeterminada utilizada por el cliente:
// Define a new command by extending PredisCommandCommand:
class BrandNewRedisCommand extends Predis Command Command
{
public function getId ()
{
return ' NEWCMD ' ;
}
}
// Inject your command in the current command factory:
$ client = new Predis Client ( $ parameters , [
' commands ' => [
' newcmd ' => ' BrandNewRedisCommand ' ,
],
]);
$ response = $ client -> newcmd ();
También existe un método para enviar comandos sin formato sin filtrar sus argumentos ni analizar respuestas. Los usuarios deben proporcionar la lista de argumentos para el comando como una matriz, siguiendo las firmas definidas en la documentación de Redis para comandos:
$ response = $ client -> executeRaw ([ ' SET ' , ' foo ' , ' bar ' ]);
Si bien es posible aprovechar las secuencias de comandos de Lua en Redis 2.6+ usando directamente EVAL
y EVALSHA
, Predis ofrece comandos de secuencias de comandos como una abstracción de nivel superior construida sobre ellos para simplificar las cosas. Los comandos de script se pueden registrar en la fábrica de comandos utilizada por el cliente y son accesibles como si fueran comandos simples de Redis, pero definen scripts de Lua que se transmiten al servidor para su ejecución remota. Internamente usan EVALSHA
de forma predeterminada e identifican un script por su hash SHA1 para ahorrar ancho de banda, pero EVAL
se usa como respaldo cuando es necesario:
// Define a new script command by extending PredisCommandScriptCommand:
class ListPushRandomValue extends Predis Command ScriptCommand
{
public function getKeysCount ()
{
return 1 ;
}
public function getScript ()
{
return <<<LUA
math.randomseed(ARGV[1])
local rnd = tostring(math.random())
redis.call('lpush', KEYS[1], rnd)
return rnd
LUA ;
}
}
// Inject the script command in the current command factory:
$ client = new Predis Client ( $ parameters , [
' commands ' => [
' lpushrand ' => ' ListPushRandomValue ' ,
],
]);
$ response = $ client -> lpushrand ( ' random_values ' , $ seed = mt_rand ());
Predis puede usar diferentes backends de conexión para conectarse a Redis. La integración integrada de Relay aprovecha la extensión Relay para PHP para obtener importantes ganancias de rendimiento, al almacenar en caché una réplica parcial del conjunto de datos de Redis en la memoria de tiempo de ejecución compartida de PHP.
$ client = new Predis Client ( ' tcp://127.0.0.1 ' , [
' connections ' => ' relay ' ,
]);
Los desarrolladores pueden crear sus propias clases de conexión para admitir backends de red completamente nuevos, ampliar las clases existentes o proporcionar implementaciones completamente diferentes. Las clases de conexión deben implementar PredisConnectionNodeConnectionInterface
o extender PredisConnectionAbstractConnection
:
class MyConnectionClass implements Predis Connection NodeConnectionInterface
{
// Implementation goes here...
}
// Use MyConnectionClass to handle connections for the `tcp` scheme:
$ client = new Predis Client ( ' tcp://127.0.0.1 ' , [
' connections ' => [ ' tcp ' => ' MyConnectionClass ' ],
]);
Para obtener una visión más detallada sobre cómo crear nuevos backends de conexión, puede consultar la implementación real de las clases de conexión estándar disponibles en el espacio de nombres PredisConnection
.
Las contribuciones a Predis son muy apreciadas, ya sea en forma de solicitudes de incorporación de nuevas funciones, correcciones de errores o simplemente informes de errores. Solo le pedimos que cumpla con las plantillas de solicitudes de publicación y extracción.
ATENCIÓN : ¡Nunca ejecute el conjunto de pruebas incluido con Predis en instancias de Redis que se ejecutan en entornos de producción o que contienen datos que le interesan!
Predis tiene un conjunto de pruebas integral que cubre todos los aspectos de la biblioteca y que opcionalmente puede realizar pruebas de integración contra una instancia en ejecución de Redis (requerido >= 2.4.0 para verificar el comportamiento correcto de la implementación de cada comando. Pruebas de integración para no compatibles Los comandos de Redis se omiten automáticamente. Si no tiene Redis en funcionamiento, las pruebas de integración se pueden desactivar. Consulte el archivo README de pruebas para obtener más detalles sobre cómo probar esta biblioteca.
Predis utiliza GitHub Actions para una integración continua y el historial de compilaciones pasadas y actuales se puede encontrar en su página de acciones.
El código de Predis se distribuye según los términos de la licencia MIT (ver LICENCIA).