-
-
Notifications
You must be signed in to change notification settings - Fork 988
Quick tour
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.
$redis = new Predis\Client();
$redis = new Predis\Client(array(
'host' => '10.0.0.1',
'port' => 6380,
));
or
$redis = new Predis\Client('redis://10.0.0.1:6380/');
$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/'
);
$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');
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 requests to Redis using Predis is really easy, but there is not only one way to deal with commands:
$redis->set('library', 'predis');
$retval = $redis->get('library');
// 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);
$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:
$cmdSet = $redis->createCommand('set', array('library', 'predis'));
$cmdSet = $redis->createCommand('set');
$cmdSet->setArgumentsArray(array('library', 'predis'));
$cmdSet = $redis->createCommand('set');
$cmdSet->setArguments('library', 'predis');
What if you need to send commands not yet defined in Predis?
$reply = $redis->rawCommand("NEWCMD $key $param1 $param2");
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);
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:
$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);
$defaultProfile = Predis\RedisServerProfile::getDefault();
echo get_class($defaultProfile); // OUTPUT: Predis\RedisServer_v1_2
$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 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).
$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();
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.
$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