1
|
# Predis #
|
2
|
|
3
|
[![Latest Stable Version](https://poser.pugx.org/predis/predis/v/stable.png)](https://packagist.org/packages/predis/predis)
|
4
|
[![Total Downloads](https://poser.pugx.org/predis/predis/downloads.png)](https://packagist.org/packages/predis/predis)
|
5
|
|
6
|
Predis is a flexible and feature-complete [Redis](http://redis.io) client library for PHP >= 5.3.
|
7
|
|
8
|
By default Predis does not require any additional C extension, but it can be optionally paired with
|
9
|
[phpiredis](https://github.com/nrk/phpiredis) to lower the overhead of serializing and parsing the
|
10
|
Redis protocol. An asynchronous implementation of the client, albeit experimental, is also available
|
11
|
through [Predis\Async](https://github.com/nrk/predis-async).
|
12
|
|
13
|
Predis can be used with [HHVM](http://www.hhvm.com) >= 2.4.0, but there are no guarantees you will
|
14
|
not run into unexpected issues (especially with the JIT compiler enabled via `Eval.Jit = true`) due
|
15
|
to HHVM being still under heavy development, thus unstable and not yet 100% compatible with PHP.
|
16
|
|
17
|
More details about the project can be found in our [frequently asked questions](FAQ.md) section or
|
18
|
on the online [wiki](https://github.com/nrk/predis/wiki).
|
19
|
|
20
|
|
21
|
## Main features ##
|
22
|
|
23
|
- Wide range of Redis versions supported (from __1.2__ to __2.8__ and unstable) using profiles.
|
24
|
- Clustering via client-side sharding using consistent hashing or custom distributors.
|
25
|
- Smart support for [redis-cluster](http://redis.io/topics/cluster-spec) (Redis >= 3.0).
|
26
|
- Support for master-slave replication configurations (write on master, read from slaves).
|
27
|
- Transparent key prefixing for all Redis commands.
|
28
|
- Command pipelining (works on both single and aggregate connections).
|
29
|
- Abstraction for Redis transactions (Redis >= 2.0) supporting CAS operations (Redis >= 2.2).
|
30
|
- Abstraction for Lua scripting (Redis >= 2.6) with automatic switching between `EVALSHA` or `EVAL`.
|
31
|
- Abstraction for `SCAN`, `SSCAN`, `ZSCAN` and `HSCAN` (Redis >= 2.8) based on PHP iterators.
|
32
|
- Connections to Redis are established lazily by the client upon the first command.
|
33
|
- Support for both TCP/IP and UNIX domain sockets and persistent connections.
|
34
|
- Support for [Webdis](http://webd.is) (both `ext-curl` and `ext-phpiredis` are needed).
|
35
|
- Support for custom connection classes for providing different network or protocol backends.
|
36
|
- Flexible system for defining and registering custom sets of supported commands or profiles.
|
37
|
|
38
|
|
39
|
## How to use Predis ##
|
40
|
|
41
|
Predis is available on [Packagist](http://packagist.org/packages/predis/predis) which allows a quick
|
42
|
installation using [Composer](http://packagist.org/about-composer). Alternatively, the library can
|
43
|
be found on our [own PEAR channel](http://pear.nrk.io) for a more traditional installation via PEAR.
|
44
|
Ultimately, archives of each release are [available on GitHub](https://github.com/nrk/predis/tags).
|
45
|
|
46
|
|
47
|
### Loading the library ###
|
48
|
|
49
|
Predis relies on the autoloading features of PHP to load its files when needed and complies with the
|
50
|
[PSR-0 standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) which makes
|
51
|
it compatible with most PHP frameworks. Autoloading is handled automatically when dependencies are
|
52
|
managed using Composer, but you can also leverage its own autoloader if you are going to use it in a
|
53
|
project or script without any PSR-0 compliant autoloading facility:
|
54
|
|
55
|
```php
|
56
|
// Prepend a base path if Predis is not available in your "include_path".
|
57
|
require 'Predis/Autoloader.php';
|
58
|
|
59
|
Predis\Autoloader::register();
|
60
|
```
|
61
|
|
62
|
It is possible to easily create a [phar](http://www.php.net/manual/en/intro.phar.php) archive from
|
63
|
the repository just by launching `bin/create-phar`. The generated phar contains a stub defining an
|
64
|
autoloader function for Predis, so you just need to require the phar to start using the library.
|
65
|
Alternatively, it is also possible to generate one single PHP file that holds every class like older
|
66
|
versions of Predis by launching `bin/create-single-file`, but this practice __is not__ encouraged.
|
67
|
|
68
|
|
69
|
### Connecting to Redis ###
|
70
|
|
71
|
When not specifying any connection parameter to create a new client, Predis assumes `127.0.0.1` and
|
72
|
`6379` as the default host and port and uses a connection timeout of 5 seconds:
|
73
|
|
74
|
```php
|
75
|
$client = new Predis\Client();
|
76
|
$client->set('foo', 'bar');
|
77
|
$value = $client->get('foo');
|
78
|
```
|
79
|
|
80
|
Connection parameters can be supplied either in the form of URI strings or named arrays. While the
|
81
|
latter is the preferred way to supply parameters, URI strings can be useful for quick configurations
|
82
|
or when parameters are read from a non-structured source:
|
83
|
|
84
|
```php
|
85
|
// Named array of connection parameters:
|
86
|
$client = new Predis\Client([
|
87
|
'scheme' => 'tcp',
|
88
|
'host' => '10.0.0.1',
|
89
|
'port' => 6379,
|
90
|
]);
|
91
|
|
92
|
// Same set of parameters, but using an URI string:
|
93
|
$client = new Predis\Client('tcp://10.0.0.1:6379');
|
94
|
```
|
95
|
|
96
|
When an array of connections parameters is provided, Predis automatically works in clustering mode
|
97
|
using client-side sharding. Both named arrays and URI strings can be mixed for providing each node
|
98
|
configuration:
|
99
|
|
100
|
```php
|
101
|
$client = new Predis\Client([
|
102
|
'tcp://10.0.0.1?alias=first-node',
|
103
|
['host' => '10.0.0.2', 'alias' => 'second-node'],
|
104
|
]);
|
105
|
```
|
106
|
|
107
|
The actual list of supported connection parameters can vary depending on each connection backend so
|
108
|
it is recommended to refer to their specific documentation for details.
|
109
|
|
110
|
|
111
|
### Client configuration ###
|
112
|
|
113
|
Various aspects of the client can be easily configured by passing options to the second argument of
|
114
|
`Predis\Client::__construct()`. Options are managed using a mini DI-alike container and their values
|
115
|
are usually lazily initialized only when needed. Predis by default supports the following options:
|
116
|
|
117
|
- `profile`: which profile to use in order to match a specific version of Redis.
|
118
|
- `prefix`: a prefix string that is automatically applied to keys found in commands.
|
119
|
- `exceptions`: whether the client should throw or return responses upon Redis errors.
|
120
|
- `connections`: connection backends or a connection factory to be used by the client.
|
121
|
- `cluster`: which backend to use for clustering (predis, redis or custom configuration).
|
122
|
- `replication`: which backend to use for replication (predis or custom configuration).
|
123
|
|
124
|
Users can provide custom option values, they are stored in the options container and can be accessed
|
125
|
later through the library.
|
126
|
|
127
|
|
128
|
### Aggregate connections ###
|
129
|
|
130
|
Predis is able to aggregate multiple connections which is the base for clustering and replication.
|
131
|
By default the client implements clustering using either client-side sharding (default) or a Redis
|
132
|
backed solution using [redis-cluster](http://redis.io/topics/cluster-tutorial). As for replication,
|
133
|
Predis can handle single-master and multiple-slaves setups by executing read operations on slaves
|
134
|
and switching to the master for write operations. The replication behaviour is fully configurable.
|
135
|
|
136
|
|
137
|
### Command pipelines ###
|
138
|
|
139
|
Pipelining can help with performances when many commands need to be sent to a server by reducing the
|
140
|
latency introduced by network round-trip timings. Pipelining also works with aggregate connections.
|
141
|
The client can execute the pipeline inside a callable block or return a pipeline instance with the
|
142
|
ability to chain commands thanks to its fluent interface:
|
143
|
|
144
|
```php
|
145
|
// Executes a pipeline inside a given callable block:
|
146
|
$responses = $client->pipeline(function ($pipe) {
|
147
|
for ($i = 0; $i < 1000; $i++) {
|
148
|
$pipe->set("key:$i", str_pad($i, 4, '0', 0));
|
149
|
$pipe->get("key:$i");
|
150
|
}
|
151
|
});
|
152
|
|
153
|
// Returns a pipeline instance with fluent interface:
|
154
|
$responses = $client->pipeline()->set('foo', 'bar')->get('foo')->execute();
|
155
|
```
|
156
|
|
157
|
|
158
|
### Transactions ###
|
159
|
|
160
|
The client provides an abstraction for Redis transactions based on `MULTI` and `EXEC` with a similar
|
161
|
interface to command pipelines:
|
162
|
|
163
|
```php
|
164
|
// Executes a transaction inside a given callable block:
|
165
|
$responses = $client->transaction(function ($tx) {
|
166
|
$tx->set('foo', 'bar');
|
167
|
$tx->get('foo');
|
168
|
});
|
169
|
|
170
|
// Returns a transaction instance with fluent interface:
|
171
|
$responses = $client->transaction()->set('foo', 'bar')->get('foo')->execute();
|
172
|
```
|
173
|
|
174
|
This abstraction can perform check-and-set operations thanks to `WATCH` and `UNWATCH` and provides
|
175
|
automatic retries of transactions aborted by Redis when `WATCH`ed keys are touched. For an example
|
176
|
of a transaction using CAS you can see [the following example](examples/TransactionWithCAS.php).
|
177
|
|
178
|
__NOTE__: the method `transaction()` is available since `v0.8.5`, older versions used `multiExec()`
|
179
|
for the same purpose but it has been deprecated and will be removed in the next major release.
|
180
|
|
181
|
|
182
|
### Customizable connection backends ###
|
183
|
|
184
|
Predis can use different connection backends to connect to Redis. Two of them leverage a third party
|
185
|
extension such as [phpiredis](https://github.com/nrk/phpiredis) resulting in major performance gains
|
186
|
especially when dealing with big multibulk responses. While one is based on PHP streams, the other
|
187
|
is based on socket resources provided by `ext-socket`. Both support TCP/IP or UNIX domain sockets:
|
188
|
|
189
|
```php
|
190
|
$client = new Predis\Client('tcp://127.0.0.1', [
|
191
|
'connections' => [
|
192
|
'tcp' => 'Predis\Connection\PhpiredisStreamConnection', // PHP streams
|
193
|
'unix' => 'Predis\Connection\PhpiredisConnection', // ext-socket
|
194
|
],
|
195
|
]);
|
196
|
```
|
197
|
|
198
|
Developers can create their own connection classes to add support for new network backends, extend
|
199
|
existing ones or provide completely different implementations. Connection classes must implement
|
200
|
`Predis\Connection\SingleConnectionInterface` or extend `Predis\Connection\AbstractConnection`:
|
201
|
|
202
|
```php
|
203
|
class MyConnectionClass implements Predis\Connection\SingleConnectionInterface
|
204
|
{
|
205
|
// Implementation goes here...
|
206
|
}
|
207
|
|
208
|
// Use MyConnectionClass to handle connections for the `tcp` scheme:
|
209
|
$client = new Predis\Client('tcp://127.0.0.1', [
|
210
|
'connections' => ['tcp' => 'MyConnectionClass'],
|
211
|
]);
|
212
|
```
|
213
|
|
214
|
For a more in-depth insight on how to create new connection backends you can refer to the actual
|
215
|
implementation of the standard connection classes available in the `Predis\Connection` namespace.
|
216
|
|
217
|
|
218
|
### Adding support for new commands ###
|
219
|
|
220
|
While we try to update Predis to stay up to date with all the commands available in Redis, you might
|
221
|
prefer to stick with an older version of the library or provide a different way to filter arguments
|
222
|
or parse responses for specific commands. To achieve that, Predis provides the ability to implement
|
223
|
new command classes to define or override commands in the server profiles used by the client:
|
224
|
|
225
|
```php
|
226
|
// Define a new command by extending Predis\Command\AbstractCommand:
|
227
|
class BrandNewRedisCommand extends Predis\Command\AbstractCommand
|
228
|
{
|
229
|
public function getId()
|
230
|
{
|
231
|
return 'NEWCMD';
|
232
|
}
|
233
|
}
|
234
|
|
235
|
// Inject your command in the current profile:
|
236
|
$client = new Predis\Client();
|
237
|
$client->getProfile()->defineCommand('newcmd', 'BrandNewRedisCommand');
|
238
|
|
239
|
$response = $client->newcmd();
|
240
|
```
|
241
|
|
242
|
|
243
|
### Scriptable commands ###
|
244
|
|
245
|
A scriptable command is just an abstraction for [Lua scripting](http://redis.io/commands/eval) that
|
246
|
aims to simplify the usage of scripting with Redis >= 2.6. Scriptable commands can be registered in
|
247
|
the server profile used by the client and are accessible as if they were plain Redis commands, but
|
248
|
they define a Lua script that gets transmitted to Redis for remote execution. Internally, scriptable
|
249
|
commands use by default [EVALSHA](http://redis.io/commands/evalsha) and identify a Lua script by its
|
250
|
SHA1 hash to save bandwidth but [EVAL](http://redis.io/commands/eval) is automatically preferred as
|
251
|
a fall back when needed:
|
252
|
|
253
|
```php
|
254
|
// Define a new scriptable command by extending Predis\Command\ScriptedCommand:
|
255
|
class ListPushRandomValue extends Predis\Command\ScriptedCommand
|
256
|
{
|
257
|
public function getKeysCount()
|
258
|
{
|
259
|
return 1;
|
260
|
}
|
261
|
|
262
|
public function getScript()
|
263
|
{
|
264
|
return <<<LUA
|
265
|
math.randomseed(ARGV[1])
|
266
|
local rnd = tostring(math.random())
|
267
|
redis.call('lpush', KEYS[1], rnd)
|
268
|
return rnd
|
269
|
LUA;
|
270
|
}
|
271
|
}
|
272
|
|
273
|
// Inject your scriptable command in the current profile:
|
274
|
$client = new Predis\Client();
|
275
|
$client->getProfile()->defineCommand('lpushrand', 'ListPushRandomValue');
|
276
|
|
277
|
$response = $client->lpushrand('random_values', $seed = mt_rand());
|
278
|
```
|
279
|
|
280
|
|
281
|
## Development ##
|
282
|
|
283
|
|
284
|
### Reporting bugs and contributing code ###
|
285
|
|
286
|
Contributions to Predis are highly appreciated either in the form of pull requests for new features,
|
287
|
bug fixes, or just bug reports. We only ask you to adhere to a [basic set of rules](CONTRIBUTING.md)
|
288
|
before submitting your changes or filing bugs on the issue tracker to make it easier for everyone to
|
289
|
stay consistent while working on the project.
|
290
|
|
291
|
|
292
|
### Test suite ###
|
293
|
|
294
|
__ATTENTION__: Do not ever run the test suite shipped with Predis against instances of Redis running
|
295
|
in production environments or containing data you are interested in!
|
296
|
|
297
|
Predis has a comprehensive test suite covering every aspect of the library. This test suite performs
|
298
|
integration tests against a running instance of Redis (>= 2.4.0 is required) to verify the correct
|
299
|
behaviour of the implementation of each command and automatically skips commands not defined in the
|
300
|
specified Redis profile. If you do not have Redis up and running, integration tests can be disabled.
|
301
|
By default the test suite is configured to execute integration tests using the profile for Redis 2.8
|
302
|
(which is the current stable version of Redis) but can optionally target a Redis instance built from
|
303
|
the `unstable` branch by modifying `phpunit.xml` and setting `REDIS_SERVER_VERSION` to `dev` so that
|
304
|
the development server profile will be used. You can refer to [the tests README](tests/README.md)
|
305
|
for more detailed information about testing Predis.
|
306
|
|
307
|
Predis uses Travis CI for continuous integration and the history for past and current builds can be
|
308
|
found [on its project page](http://travis-ci.org/nrk/predis).
|
309
|
|
310
|
|
311
|
## Other ##
|
312
|
|
313
|
|
314
|
### Project related links ###
|
315
|
|
316
|
- [Source code](https://github.com/nrk/predis)
|
317
|
- [Wiki](https://wiki.github.com/nrk/predis)
|
318
|
- [Issue tracker](https://github.com/nrk/predis/issues)
|
319
|
- [PEAR channel](http://pear.nrk.io)
|
320
|
|
321
|
|
322
|
### Author ###
|
323
|
|
324
|
- [Daniele Alessandri](mailto:suppakilla@gmail.com) ([twitter](http://twitter.com/JoL1hAHN))
|
325
|
|
326
|
|
327
|
### License ###
|
328
|
|
329
|
The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)).
|