Skip to content

Quick tour

Till Krüss edited this page Mar 2, 2023 · 7 revisions

Connecting to a server

Predis offers various means to connect to a single server or a cluster of servers. By specifying two or more servers, Predis automatically switches over a clustered connection that transparently handles client-side sharding over multiple connections. It should be noted that clustered connections have a little more overhead when compared to single connections (that is, when Predis is connected only to a single server) due to a more complex internal structure needed to support consistent hashing.

Connect to the default host (127.0.0.1) and port (6379)

$redis = new Predis\Client();

Connect to a server using parameters

$redis = new Predis\Client(array(
    'host' => '10.0.0.1', 
    'port' => 6380, 
));

or

$redis = new Predis\Client('redis://10.0.0.1:6380/');

Connect to multiple servers

$redis = new Predis\Client(array(
    array('host' => '10.0.0.1'), 
    array('host' => '10.0.0.2'), 
));

or

$redis = new Predis\Client(array(
    'redis://10.0.0.1/', 
    'redis://10.0.0.1/', 
));

or

$redis = Predis\Client::create(
    array('host' => '10.0.0.1'), 
    array('host' => '10.0.0.2')
);

or

$redis = Predis\Client::create(
    'redis://10.0.0.1/', 
    'redis://10.0.0.1/'
);

Automatically perform authentication and database selection when connecting

$redis = new Predis\Client(array(
    'host'     => '10.0.0.1', 
    'password' => 'secret', 
    'database' => 10, 
));

or

$redis = new Predis\Client('redis://10.0.0.1/?password=secret&database=10');

Supported connection parameters

parameter meaning default
host IP address / hostname of the server 127.0.0.1
port TCP port on which the server is listening to 6379
password password for authenticating against the server no password is used
database database index to select when connected no index is set, the default Redis database is used
timeout timeout in seconds for connecting to a server 5
read_write_timeout timeout for read/write operations on the network socket system default (NOTE: to disable r/w timeouts use -1)

Sending commands

Sending requests to Redis using Predis is really easy, but there is not only one way to deal with commands:

The simple (and most common) way

$redis->set('library', 'predis');
$retval = $redis->get('library');

The long (but more programmatic) way

// Client::createCommand uses the current server profile
// to create and return a new command instance
$cmdSet = $redis->createCommand('set');
$cmdSet->setArgumentsArray(array('library', 'predis'));
$cmdSetReply = $redis->executeCommand($cmdSet);
$cmdGet = $redis->createCommand('get');
$cmdGet->setArgumentsArray(array('library'));
$cmdGetReply = $redis->executeCommand($cmdGet);

The longest (and partially discouraged) way

$cmdSet = new Predis\Commands\Set();
$cmdSet->setArgumentsArray(array('library', 'predis'));
$cmdSetReply = $redis->executeCommand($cmdSet);
$cmdGet = new Predis\Commands\Get();
$cmdGet->setArgumentsArray(array('library'));
$cmdGetReply = $redis->executeCommand($cmdGet);

You also have different ways to set the arguments of a command when working on command instances:

Pass a dynamic list of arguments when creating an instance of a command

$cmdSet = $redis->createCommand('set', array('library', 'predis'));

Pass a dynamic list of arguments on an existing command instance

$cmdSet = $redis->createCommand('set');
$cmdSet->setArgumentsArray(array('library', 'predis'));

Pass a fixed list of arguments on an existing command instance

$cmdSet = $redis->createCommand('set');
$cmdSet->setArguments('library', 'predis');

What if you need to send commands not yet defined in Predis?

Send raw commands** (it does not currently work with clustered connections)

$reply = $redis->rawCommand("NEWCMD $key $param1 $param2");

Define your own commands by extending one of the following base classes

  • Predis\Command
  • Predis\InlineCommand
  • Predis\BulkCommand
  • Predis\MultiBulkCommand
class BrandNewRedisCommand extends \Predis\InlineCommand {
    public function getCommandId() { return 'NEWCMD'; }
}
$redis->getProfile()->registerCommand('BrandNewRedisCommand', 'newcmd');
$reply = $redis->newcmd($key, $param1, $param2);

Server profiles

Predis introduced the concept of server profiles to allow developers to specify, in a programmatic way, which Redis version they are going to connect to. This means that you can know beforehand which commands or features are supported by the selected Redis version and allows us to handle eventual behavioral differences in certain commands. As of today there are three predefined profile classes: Predis\RedisServer_v1_0 (Redis v1.0), Predis\RedisServer_v1_2 (Redis v1.2) and Predis\RedisServer_vNext (the development version of Redis). When you create an instance of Predis\Client, the default server profile being used is the latest stable version of Redis available at release time, but you can always force Predis to use a different profile:

Set a different server profile when instanciating a new Predis\Client instance

$profile1_0 = new Predis\RedisServer_v1_0();
printf("MSET SUPPORTED: %s\n", $profile1_0->supportsCommand('mset') ? 'YES' : 'NO');
$profile1_2 = new Predis\RedisServer_v1_2();
printf("MSET SUPPORTED: %s\n", $profile1_2->supportsCommand('mset') ? 'YES' : 'NO');
$redis = new Predis\Client('redis://127.0.0.1/', $profile1_2);

Get an instance of the default server profile supported by the current version of Predis

$defaultProfile = Predis\RedisServerProfile::getDefault();
echo get_class($defaultProfile);        // OUTPUT: Predis\RedisServer_v1_2

Get an instance of a server profile supported by Predis by using a version string

$profile = Predis\RedisServerProfile::get('1.2');
echo get_class($profile);        // OUTPUT: Predis\RedisServer_v1_2
$profile = Predis\RedisServerProfile::get('dev');
echo get_class($profile);        // OUTPUT: Predis\RedisServer_vNext

Pipelining

Pipelining can help with performances when you need to issue a whole set of commands to Redis. This is done by recording the commands issued to the client without actually sending them to the server, playing them all at once over the wire when flushing the pipeline (send the commands) and then listening to what the server has to tell us (read the responses).

Initialize a pipeline inside of a block of code using an anonymous function

$replies = $redis->pipeline(function($pipe) {
    $pipe->ping();
    $pipe->flushdb();
    $pipe->incrby('counter', 10);
    $pipe->exists('counter');
    $pipe->mget('does_not_exist', 'counter');
});
```php

### Initialize a pipeline and return an instance to play with
```php
$pipe = $redis->pipeline();
$pipe->ping();
$pipe->flushdb();
$pipe->incrby('counter', 10);
$pipe->exists('counter');
$pipe->mget('does_not_exist', 'counter');
$replies = $pipe->execute();

Client-side sharding

The key-value model allows you to easily distribute your data across several servers and this is usually achieved by hashing the keys against a list of servers to select which one will be used to store their respective values. The same data-partitioning strategy can be used with Redis using a client library capable of handling connections to more than one server, but this is not enough to guarantee a consistent distribution and accessibility of your data as time passes. Predis supports consistent hashing when storing your list of servers, so that adding or removing a server does not affect the pre-existing distribution and availability of data on the others. Key tags are another interesting feature that allows you to decide which portion of a key should be hashed against the server list so you can redirect a subset of keys to the same instance. E.g., instead of using plain keys like "uid:1000:username" and "uid:1000:password" that will almost surely produce a different hash (and thus, sent on different servers) you can go with "{uid:1000}:username" and "{uid:1000}:password", where the curly brackets define which part of the key will be hashed. Everything is handled transparently, even when using pipelines.

Initialize a clustered client and set/retrieve key-values using key tags

$redis = Predis\Client::create(
    'redis://10.0.0.1/', 
    'redis://10.0.0.2/'
);
$redis->set('{uid:1000}:username', 'nrk');
$redis->set('{uid:1000}:password', md5('mystrongpassword'));
$username = $redis->get('{uid:1000}:username'); // nrk
$password = $redis->get('{uid:1000}:password'); // c924729b0e04eb0d21908a7454c0218a