- Predis
Predis is applicable to the use of PHP version 5.3 and above in Redis, including the use of clusters.
major function
- Support various versions of redis (from 2.0 to 3.0 and unstable)
- Use hash method or user-defined method to partition the client of nodes in the cluster
- support Redis cluster (Redis>= 3.0).
- Support read / write separation of master / slave structure
- Support all known Redis client commands
Mode of use
Predis download address: PEAR channel as well as GitHub mode.
Load dependent packages
Predis relies on PHP's automatic loading function to load its files when needed and comply with the PSR-4 standard. Use the following:
// Load from the Predis root directory. Unless the file is in include_path require 'Predis/Autoloader.php'; Predis\Autoloader::register(); Copy code
Connect to Redis
If you do not add any parameters during the connection, 127.0.0.1 and 6379 will be used as the default host and port by default, and the connection timeout is 5 seconds. For example:
$client = new Predis\Client(); $client->set('foo', 'bar'); $value = $client->get('foo'); Copy code
If connection parameters need to be added, they can be in the form of URI or array. For example:
// Array form $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => '10.0.0.1', 'port' => 6379, ]); // URI form: $client = new Predis\Client('tcp://10.0.0.1:6379'); Copy code
When using array form. Predis automatically switches to cluster mode and uses the client's sharding logic. In addition, parameters can also be mixed with URI s and arrays, such as:
$client = new Predis\Client([ 'tcp://10.0.0.1?alias=first-node', ['host' => '10.0.0.2', 'alias' => 'second-node'], ]); Copy code
Client configuration
More configuration parameters of the Client can be passed in through the second parameter:
$client = new \Predis\Client( $connection_parameters, ['profile' => '2.8', 'prefix' => 'sample:'] ); Copy code
Redis will give default values to the required parameters, mainly including:
- profile: configuration for a specific version, because different versions may have different effects on the same operation
- Prefix: automatically prefix the key to be processed
- Exceptions: whether to return results when redis makes an error
- connections: the connection factory to be used by the client
- Cluster: which background is used in the cluster (predis, redis or client configuration)
- replication: which background (predis or client configuration) the master / slave uses
- aggregate: merge connection methods (overwrite cluster and replication)
Merge connection
Predis supports the connection of clusters and master / slave structures. By default, the fragmentation logic of the client or the method provided by the Redis server can be used, that is: redis cluster. In the master / slave structure, Predis supports the form of one master and multiple slaves, and connects to the slave during read operations and to the host during write operations.
Master / slave structure
Master / slave configuration can be performed during client connection. After configuration, the slave will be connected when the read operation is performed; The host is connected when a write operation is performed. Achieve read-write separation. The following is the basic master / slave configuration:
$parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2?alias=slave-01']; $options = ['replication' => true]; $client = new Predis\Client($parameters, $options); Copy code
Although Predis can recognize read / write operations, Eval and evalsha are two special cases. Because the client does not know whether there are write operations in the LUA script, these two operations are usually performed on the Master. Although this is the default behavior, if write operations are not included in some Lua scripts, the client may still execute on the slave. Can be specified by configuration.
$LUA_SCRIPT = "......some lua code......"; $parameters = ['tcp://10.0.0.1?alias=master', 'tcp://10.0.0.2?alias=slave-01']; $options = ['replication' => function () { // Force the specified to execute on the slave without switching to the master $strategy = new Predis\Replication\ReplicationStrategy(); $strategy -> setScriptReadOnly($LUA_SCRIPT); return new Predis\Connection\Aggregate\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. Copy code
colony
The cluster function can be realized by passing simple and configuration, and it is partitioned on the client. However, if you want to use the redis cluster function (available in the version after Redis 3.0). It can be configured as follows:
$parameters = ['tcp://10.0.0.1', 'tcp://10.0.0.2']; $options = ['cluster' => 'redis']; $client = new Predis\Client($parameters, $options); Copy code
When using redis cluster, you don't need to pass all the nodes in the cluster in the parameters, just a few. Predis will automatically get all hash slot maps from a server.
Note: at present, Predis does not support the master / slave structure in redis cluster
Command pipeline
The pipeline helps to improve the performance of a large number of commands to be sent. It can reduce the round-trip delay of the network. For example, there are two commands for data: -Send command to server -Server execution command -Return structure to client
Each operation must be executed. The pipeline means that multiple commands can be packaged and sent to the server together. After all commands are executed, the final results will be returned. There are two ways to use pipes. One is through callback function; One is through the interface:
// Execute command channel by callback: $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"); } }); // Command channel used in interface form: $responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute(); Replication generation
affair
Redis can use MULTI and EXEC commands to implement transaction functions. Here, you can directly use the command channel:
// Callback method: $responses = $client->transaction(function ($tx) { $tx->set('foo', 'bar'); $tx->get('foo'); }); // Interface mode: $responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute(); Copy code
We can use WATCH and UNWATCH to implement CAS (check and set). For example:
function zpop($client, $key) { $element = null; $options = array( 'cas' => true, // Use CAS mode 'watch' => $key, // key to monitor 'retry' => 3, // Number of retries on error ); $client->transaction($options, function ($tx) use ($key, &$element) { @list($element) = $tx->zrange($key, 0, 0); if (isset($element)) { $tx->multi(); // Open transaction $tx->zrem($key, $element); } }); return $element; } $client = new Predis\Client($single_server); $zpopped = zpop($client, 'zset'); Copy code
Custom command
If we upgrade Redis to a new version and the processing methods of some commands are changed, but we want to use the previous logic, we can customize the commands:
// Customize a class and inherit Predis\Command\Command: class BrandNewRedisCommand extends Predis\Command\Command { public function getId() { return 'NEWCMD'; } } // To register a new custom command: $client = new Predis\Client(); $client->getProfile()->defineCommand('newcmd', 'BrandNewRedisCommand'); $response = $client->newcmd(); Copy code
LUA command
Redis version after 2.6 can be used EVAL and EVALSHA To execute LUA scripts. Predis supports a simple interface to support this function. LUA scripts can be on the server side or passed in through parameters. By default, the EVALSHA It can also be standby EVAL :
// Define a script execution command, which inherits Predis\Command\ScriptCommand: class ListPushRandomValue extends Predis\Command\ScriptCommand { public function getKeysCount() { return 1; } public function getScript() { return << } } // To register a new command: $client = new Predis\Client(); $client->getProfile()->defineCommand('lpushrand', 'ListPushRandomValue'); $response = $client->lpushrand('random_values', $seed = mt_rand()); Copy code
performance
Native test
Predis is a pure PHP extension, so its performance may be insufficient. But it should be enough in practical use. Here are some test data using PHP 5.5.6 and Redis 2.8:
21000 SET/second key and value All use 12 type size 21000 GET/second use _KEYS *_ Command at 0.130 30000 queries per second key Copy code
Extensions similar to Predis include: phpredis , an extension written in C. The test performance results are as follows:
30100 SET/second key and value All use 12 type size 29400 GET/second use _KEYS *_ Command at 0.035 30000 queries per second key Copy code
phpredis looks a lot faster. But in fact, the difference is not too much, and one is written in C and the other is a pure php extension. And the above test is very simple and not conclusive. Let's take a look at tests similar to those in a real production environment.
External network environment test
Here are some tests for connecting to the local machine. Now try connecting to the remote server:
Predis: 3200 SET/second key and value All use 12 type size 3200 GET/second use _KEYS *_ Command at 0.132 30000 queries per second key phpredis: 3500 SET/second key and value All use 12 type size 3500 GET/second use _KEYS *_ Command at 0.045 30000 queries per second key Copy code
We can see that the efficiency of the two is similar, because the delay of the website will be a very important problem of performance. Predis can use the command channel, saving a lot of time.
Last choice
Predis can be compatible with various versions of redis (currently supports 1.2 to 2.8), and can be compatible with different versions through custom commands. phpredis has some advantages on this machine. Alternatively, you can use both.