Ein flexibler und funktionsreicher Redis-Client für PHP 7.2 und höher.
Weitere Details zu diesem Projekt finden Sie in den häufig gestellten Fragen.
EVALSHA
oder EVAL
.SCAN
, SSCAN
, ZSCAN
und HSCAN
(Redis >= 2.8) basierend auf PHP-Iteratoren.Diese Bibliothek ist auf Packagist zu finden und erleichtert die Verwaltung von Projektabhängigkeiten mit Composer. Komprimierte Archive jeder Veröffentlichung sind auf GitHub verfügbar.
composer require predis/predis
Predis verlässt sich auf die Autoloading-Funktionen von PHP, um seine Dateien bei Bedarf zu laden, und entspricht dem PSR-4-Standard. Das automatische Laden erfolgt automatisch, wenn Abhängigkeiten über Composer verwaltet werden. Es ist jedoch auch möglich, einen eigenen Autoloader in Projekten oder Skripten zu nutzen, die über keine Autoload-Funktion verfügen:
// Prepend a base path if Predis is not available in your "include_path".
require ' Predis/Autoloader.php ' ;
Predis Autoloader:: register ();
Beim Erstellen einer Client-Instanz ohne Übergabe von Verbindungsparametern geht Predis 127.0.0.1
und 6379
als Standardhost und -port aus. Das Standard-Timeout für den connect()
-Vorgang beträgt 5 Sekunden:
$ client = new Predis Client ();
$ client -> set ( ' foo ' , ' bar ' );
$ value = $ client -> get ( ' foo ' );
Verbindungsparameter können entweder in Form von URI-Strings oder benannten Arrays bereitgestellt werden. Letzteres ist die bevorzugte Methode zur Bereitstellung von Parametern. URI-Zeichenfolgen können jedoch nützlich sein, wenn Parameter aus nicht strukturierten oder teilweise strukturierten Quellen gelesen werden:
// 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 ' );
Auf passwortgeschützte Server kann zugegriffen werden, indem password
zum Parametersatz hinzugefügt wird. Wenn ACLs auf Redis >= 6.0 aktiviert sind, sind sowohl username
als auch password
für die Benutzerauthentifizierung erforderlich.
Es ist auch möglich, über UNIX-Domänen-Sockets eine Verbindung zu lokalen Instanzen von Redis herzustellen. In diesem Fall müssen die Parameter das unix
-Schema verwenden und einen Pfad für die Socket-Datei angeben:
$ client = new Predis Client ([ ' scheme ' => ' unix ' , ' path ' => ' /path/to/redis.sock ' ]);
$ client = new Predis Client ( ' unix:/path/to/redis.sock ' );
Der Client kann die TLS/SSL-Verschlüsselung nutzen, um eine Verbindung zu gesicherten Remote-Redis-Instanzen herzustellen, ohne einen SSL-Proxy wie Stunnel konfigurieren zu müssen. Dies kann nützlich sein, wenn Sie eine Verbindung zu Knoten herstellen, die bei verschiedenen Cloud-Hosting-Anbietern ausgeführt werden. Die Verschlüsselung kann mithilfe des tls
-Schemas und einer Reihe geeigneter Optionen aktiviert werden, die über den ssl
Parameter übergeben werden:
// 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 ' );
Die Verbindungsschemata redis
(Alias von tcp
) und rediss
(Alias von tls
) werden ebenfalls unterstützt, mit dem Unterschied, dass URI-Strings, die diese Schemata enthalten, gemäß den Regeln analysiert werden, die in den jeweiligen vorläufigen IANA-Registrierungsdokumenten beschrieben sind.
Die tatsächliche Liste der unterstützten Verbindungsparameter kann je nach Verbindungs-Backend variieren. Es wird daher empfohlen, sich für Einzelheiten auf die jeweilige Dokumentation oder Implementierung zu beziehen.
Predis kann mehrere Verbindungen aggregieren, indem es ein Array von Verbindungsparametern und die entsprechende Option bereitstellt, um den Client anzuweisen, wie diese aggregiert werden sollen (Clustering, Replikation oder eine benutzerdefinierte Aggregationslogik). Benannte Arrays und URI-Strings können gemischt werden, wenn Konfigurationen für jeden Knoten bereitgestellt werden:
$ client = new Predis Client ([
' tcp://10.0.0.1?alias=first-node ' , [ ' host ' => ' 10.0.0.2 ' , ' alias ' => ' second-node ' ],
], [
' cluster ' => ' predis ' ,
]);
Weitere Einzelheiten finden Sie im Abschnitt „Aggregatverbindungen“ dieses Dokuments.
Verbindungen zu Redis sind verzögert, was bedeutet, dass der Client nur dann eine Verbindung zu einem Server herstellt, wenn dies erforderlich ist. Es wird zwar empfohlen, den Client unter der Haube seine eigenen Aufgaben erledigen zu lassen, es kann jedoch vorkommen, dass es dennoch gewünscht ist, die Kontrolle darüber zu haben, wann die Verbindung geöffnet oder geschlossen wird: Dies kann leicht durch den Aufruf $client->connect()
erreicht werden. $client->connect()
und $client->disconnect()
. Bitte beachten Sie, dass die Auswirkungen dieser Methoden auf Aggregatverbindungen je nach spezifischer Implementierung unterschiedlich sein können.
Viele Aspekte und Verhaltensweisen des Clients können konfiguriert werden, indem bestimmte Clientoptionen an das zweite Argument von PredisClient::__construct()
übergeben werden:
$ client = new Predis Client ( $ parameters , [ ' prefix ' => ' sample: ' ]);
Optionen werden mithilfe eines Mini-DI-ähnlichen Containers verwaltet und ihre Werte können nur bei Bedarf verzögert initialisiert werden. Die in Predis standardmäßig unterstützten Client-Optionen sind:
prefix
: Präfixzeichenfolge, die auf jede in Befehlen gefundene Taste angewendet wird.exceptions
: ob der Client bei Redis-Fehlern Antworten auslösen oder zurückgeben soll.connections
: Liste der Verbindungs-Backends oder einer Verbindungs-Factory-Instanz.cluster
: Gibt ein Cluster-Backend an ( predis
, redis
oder Callable).replication
: Gibt ein Replikations-Backend an ( predis
, sentinel
oder Callable).aggregate
: Konfiguriert den Client mit einer benutzerdefinierten Aggregatverbindung (aufrufbar).parameters
: Liste der Standardverbindungsparameter für Aggregatverbindungen.commands
: Gibt eine Befehlsfabrikinstanz an, die über die Bibliothek verwendet werden soll.Benutzer können auch benutzerdefinierte Optionen mit Werten oder aufrufbaren Objekten (zur verzögerten Initialisierung) bereitstellen, die im Optionscontainer zur späteren Verwendung über die Bibliothek gespeichert werden.
Aggregierte Verbindungen sind die Grundlage, auf der Predis Clustering und Replikation implementiert. Sie werden verwendet, um mehrere Verbindungen zu einzelnen Redis-Knoten zu gruppieren und die spezifische Logik zu verbergen, die erforderlich ist, um sie je nach Kontext ordnungsgemäß zu verarbeiten. Aggregatverbindungen erfordern normalerweise eine Reihe von Verbindungsparametern zusammen mit der entsprechenden Clientoption, wenn eine neue Clientinstanz erstellt wird.
Predis kann so konfiguriert werden, dass es im Clustering-Modus mit einem traditionellen clientseitigen Sharding-Ansatz arbeitet, um einen Cluster unabhängiger Knoten zu erstellen und den Schlüsselraum unter ihnen zu verteilen. Dieser Ansatz erfordert eine Art externe Gesundheitsüberwachung der Knoten und erfordert, dass der Schlüsselraum manuell neu ausgeglichen wird, wenn Knoten hinzugefügt oder entfernt werden:
$ parameters = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' cluster ' => ' predis ' ];
$ client = new Predis Client ( $ parameters );
Zusammen mit Redis 3.0 wurde eine neue überwachte und koordinierte Art des Clusterings in Form von Redis-Cluster eingeführt. Dieser Ansatz verwendet einen anderen Algorithmus zur Verteilung der Schlüsselräume, wobei Redis-Knoten sich selbst koordinieren, indem sie über ein Gossip-Protokoll kommunizieren, um den Gesundheitsstatus, den Neuausgleich, die Knotenerkennung und die Anforderungsumleitung zu verwalten. Um eine Verbindung zu einem von redis-cluster verwalteten Cluster herzustellen, benötigt der Client eine Liste seiner Knoten (nicht unbedingt vollständig, da er bei Bedarf automatisch neue Knoten erkennt) und die auf redis
eingestellten cluster
Client-Optionen:
$ 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 );
Der Client kann so konfiguriert werden, dass er in einem Einzel-Master-/Mehrfach-Slave-Setup betrieben wird, um eine bessere Dienstverfügbarkeit zu gewährleisten. Bei Verwendung der Replikation erkennt Predis schreibgeschützte Befehle und sendet sie an einen zufälligen Slave, um eine Art Lastausgleich zu gewährleisten, und wechselt zum Master, sobald es einen Befehl erkennt, der eine Operation ausführt, die letztendlich zu einer Änderung führen würde der Schlüsselraum oder der Wert eines Schlüssels. Anstatt einen Verbindungsfehler auszulösen, wenn ein Slave ausfällt, versucht der Client, auf einen anderen der in der Konfiguration bereitgestellten Slaves zurückzugreifen.
Die Grundkonfiguration, die für die Verwendung des Clients im Replikationsmodus erforderlich ist, erfordert die Identifizierung eines Redis-Servers als Master (dies kann über Verbindungsparameter erfolgen, indem der role
auf master
gesetzt wird) und eines oder mehrerer Slaves (in diesem Fall wird role
auf slave
gesetzt). für Slaves ist optional):
$ 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 );
Die obige Konfiguration verfügt über eine statische Liste von Servern und basiert vollständig auf der Logik des Clients. Für eine robustere HA-Umgebung ist es jedoch möglich, sich auf redis-sentinel
zu verlassen, wobei Sentinel-Server als Autoritätsquelle für Clients für die Diensterkennung fungieren. Die Mindestkonfiguration, die der Client für die Arbeit mit Redis-Sentinel benötigt, ist eine Liste von Verbindungsparametern, die auf eine Reihe von Sentinel-Instanzen verweisen, wobei die replication
auf sentinel
und die service
auf den Namen des Dienstes festgelegt sind:
$ 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 );
Wenn die Master- und Slave-Knoten so konfiguriert sind, dass sie eine Authentifizierung von Clients erfordern, muss über die Client-Option der globalen parameters
ein Passwort bereitgestellt werden. Mit dieser Option kann auch ein anderer Datenbankindex angegeben werden. Das Client-Options-Array würde dann wie folgt aussehen:
$ options = [
' replication ' => ' sentinel ' ,
' service ' => ' mymaster ' ,
' parameters ' => [
' password ' => $ secretpassword ,
' database ' => 10 ,
],
];
Während Predis in der Lage ist, zwischen Befehlen zu unterscheiden, die Schreib- und Nur-Lese-Vorgänge ausführen, stellen EVAL
und EVALSHA
einen Eckfall dar, bei dem der Client zum Master-Knoten wechselt, weil er nicht erkennen kann, wann ein Lua-Skript sicher auf Slaves ausgeführt werden kann. Während dies tatsächlich das Standardverhalten ist, ist es möglich, wenn bestimmte Lua-Skripte keine Schreibvorgänge ausführen, einen Hinweis bereitzustellen, der den Client anweist, bei der Ausführung bei Slaves zu bleiben:
$ 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.
Das examples
enthält einige Skripts, die veranschaulichen, wie der Client konfiguriert und verwendet werden kann, um die Replikation sowohl in einfachen als auch in komplexen Szenarios zu nutzen.
Pipelining kann die Leistung verbessern, wenn viele Befehle an einen Server gesendet werden müssen, indem es die durch Netzwerk-Roundtrip-Timings verursachte Latenz reduziert. Pipelining funktioniert auch mit Aggregatverbindungen. Der Client kann die Pipeline innerhalb eines aufrufbaren Blocks ausführen oder eine Pipeline-Instanz mit der Möglichkeit zur Befehlsverkettung dank seiner fließenden Schnittstelle zurückgeben:
// 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 ();
Der Client stellt eine Abstraktion für Redis-Transaktionen basierend auf MULTI
und EXEC
mit einer ähnlichen Schnittstelle zu Befehlspipelines bereit:
// 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 ();
Diese Abstraktion kann dank WATCH
und UNWATCH
Check-and-Set-Vorgänge durchführen und bietet automatische Wiederholungsversuche von Transaktionen, die von Redis abgebrochen wurden, wenn WATCH
ed-Tasten berührt werden. Ein Beispiel für eine Transaktion mit CAS finden Sie im folgenden Beispiel.
Während wir versuchen, Predis zu aktualisieren, um mit allen in Redis verfügbaren Befehlen auf dem neuesten Stand zu bleiben, möchten Sie vielleicht lieber bei einer alten Version der Bibliothek bleiben oder eine andere Möglichkeit bieten, Argumente zu filtern oder Antworten für bestimmte Befehle zu analysieren. Um dies zu erreichen, bietet Predis die Möglichkeit, neue Befehlsklassen zu implementieren, um Befehle in der vom Client verwendeten Standardbefehlsfabrik zu definieren oder zu überschreiben:
// 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 ();
Es gibt auch eine Methode zum Senden von Rohbefehlen, ohne deren Argumente zu filtern oder Antworten zu analysieren. Benutzer müssen die Liste der Argumente für den Befehl als Array bereitstellen und dabei den Signaturen folgen, die in der Redis-Dokumentation für Befehle definiert sind:
$ response = $ client -> executeRaw ([ ' SET ' , ' foo ' , ' bar ' ]);
Während es möglich ist, Lua-Skripting auf Redis 2.6+ direkt mit EVAL
und EVALSHA
zu nutzen, bietet Predis Skriptbefehle als eine darauf aufbauende Abstraktion höherer Ebene an, um die Dinge zu vereinfachen. Skriptbefehle können in der vom Client verwendeten Befehlsfabrik registriert werden und sind wie einfache Redis-Befehle zugänglich. Sie definieren jedoch Lua-Skripte, die zur Remote-Ausführung an den Server übertragen werden. Intern verwenden sie standardmäßig EVALSHA
und identifizieren ein Skript anhand seines SHA1-Hashs, um Bandbreite zu sparen. Bei Bedarf wird jedoch EVAL
als Ersatz verwendet:
// 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 kann verschiedene Verbindungs-Backends verwenden, um eine Verbindung zu Redis herzustellen. Die integrierte Relay-Integration nutzt die Relay-Erweiterung für PHP für erhebliche Leistungssteigerungen, indem eine Teilreplik des Redis-Datensatzes im gemeinsam genutzten PHP-Laufzeitspeicher zwischengespeichert wird.
$ client = new Predis Client ( ' tcp://127.0.0.1 ' , [
' connections ' => ' relay ' ,
]);
Entwickler können ihre eigenen Verbindungsklassen erstellen, um ganz neue Netzwerk-Backends zu unterstützen, bestehende Klassen zu erweitern oder völlig andere Implementierungen bereitzustellen. Verbindungsklassen müssen PredisConnectionNodeConnectionInterface
implementieren oder PredisConnectionAbstractConnection
erweitern:
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 ' ],
]);
Für einen detaillierteren Einblick in die Erstellung neuer Verbindungs-Backends können Sie sich die tatsächliche Implementierung der Standardverbindungsklassen ansehen, die im PredisConnection
-Namespace verfügbar sind.
Beiträge zu Predis werden sehr geschätzt, sei es in Form von Pull-Requests für neue Funktionen, Fehlerbehebungen oder einfach nur Fehlerberichte. Wir bitten Sie lediglich, sich an die Issue- und Pull-Request-Vorlagen zu halten.
ACHTUNG : Führen Sie die mit Predis gelieferte Testsuite niemals gegen Instanzen von Redis aus, die in Produktionsumgebungen ausgeführt werden oder Daten enthalten, an denen Sie interessiert sind!
Predis verfügt über eine umfassende Testsuite, die jeden Aspekt der Bibliothek abdeckt und optional Integrationstests für eine laufende Instanz von Redis (erforderlich >= 2.4.0) durchführen kann, um das korrekte Verhalten der Implementierung jedes Befehls zu überprüfen. Integrationstests für nicht unterstützte Redis-Befehle werden automatisch übersprungen. Wenn Redis nicht ausgeführt wird, können Integrationstests deaktiviert werden. Weitere Informationen zum Testen dieser Bibliothek finden Sie in der README-Datei zu den Tests.
Predis nutzt GitHub Actions für die kontinuierliche Integration und der Verlauf vergangener und aktueller Builds ist auf der Aktionsseite zu finden.
Der Code für Predis wird unter den Bedingungen der MIT-Lizenz verteilt (siehe LIZENZ).