Releases: predis/predis
Predis v0.8.6
This is a maintenance release for the 0.8 series with some improvements to existing features. What follows is an overview of the changes and bug fixes introduced in this new release, details are also available in the CHANGELOG.
New features
Redis commands
- Redis 2.8 is the new default server profile. There are no backwards incompatible changes, Redis 2.8 only added new commands so it is safe to switch.
- New commands added to the
2.8
profile:PFADD
,PFCOUNT
,PFMERGE
,ZLEXCOUNT
,ZRANGEBYLEX
andZREMRANGEBYLEX
.
Improvements
Redis Cluster
When coupled with Redis >= 3.0.0b1 you can now use key hash tags (e.g. key:{hash:tag}
) to force certain keys to be stored on the same node, just like it happens with the good old client-side sharding. See commit ba2ffb6.
Bug fixes
- Minor tweaks to make this version of Predis compatible with HHVM >= 2.4.0.
- Using Redis sentinel does not break the parsing of responses to
INFO
anymore. See issue #154 and commit f4a950b. INCRBYFLOAT
is now handled as expected in cluster and replication configurations. See issue #159 and commit c2ae1c6.- Fixed the parsing procedure for the output of
CLUSTER NODES
when fetching the slots map from a node and redis-cluster has slaves in its configuration. See issue #165 and commit e148dc8. NOTE: the newCLUSTER SLOTS
command is the proper way to fetch the slots map now, but we'll stick with the old method for this patch release of v0.8 while v1.0.0 will rely on it by default. - Prevent a stack overflow when iterating over large Redis collections using our abstraction for cursor-based iterators. See issue #182 and commit b77da84.
- Properly discards transactions when the server immediately returns an error response (e.g.
-OOM
or-ERR
on invalid arguments for a command) instead of a+QUEUED
response. See issue #187 and commit 74817b5.
Future development
Believe me, Predis v1.0.0 is on its way and will be released really soon... this time I mean it for real ;-) That said, v0.8 will still be maintaned for a while with a few more patch releases mainly targeted at improving redis-cluster support as much as possible and fixing issues.
Additional notes
Downloads
Predis v0.8.5
This is a maintenance release for the 0.8 series with some improvements to existing features. What follows is an overview of the changes and bug fixes introduced in this new release, details are also available in the CHANGELOG.
New features
Redis commands
- Added a new server profile for Redis 2.8. The default value for the
profile
client option still targets Redis 2.6 and thedev
profile now targets Redis 3.0. - New commands added to the
2.8
profile:SCAN
,SSCAN
,ZSCAN
andHSCAN
to the server profile for Redis 2.8.
Collection iterators
The new cursor-based iterator commands available starting from Redis 2.8 make it possible to iterate Redis collections without blocking the server but developers still need to implement some logic in their applications to fully leverage them. To ease the usage of such commands we added some abstractions in the Predis\Collection
namespace in the form of plain old PHP iterators, making it possible to fully iterate Redis collections in your PHP code with something as simple as foreach
.
- Keyspace iterator:
Predis\Collection\Iterator\Keyspace
based onSCAN
. - Set iterator:
Predis\Collection\Iterator\SetKey
based onSSCAN
. - Sorted set iterator:
Predis\Collection\Iterator\SortedSetKey
based onZSSCAN
. - Hash iterator:
Predis\Collection\Iterator\HashKey
based onHSCAN
.
Redis do not have a cursor-based iterator for lists but we added an abstraction with Predis\Collection\Iterator\ListKey
based on LRANGE
that tries to mimic a similar behavior while not being exactly the same thing.
You can find some examples here.
Raw commands
It is possible to execute raw commands using Predis\Command\RawCommand
and a variable list of command arguments. The main difference with the usual approach is that input arguments are not filtered and complex responses are not parsed, which also means arguments must follow the exact same signature of the command as defined by Redis. Obviously there is no need to create and register a new class to use them:
$command = Predis\Command\RawCommand::create('SET', 'foo', 'bar');
$response = $client->executeCommand($command);
Executing commands in this way can be useful to implement internal features, when the user-specified server profile is not accessible or when you need to make sure that your code will not be affected by different argument filtering or response parsing implementations.
This feature will be further improved in the next major release.
Improvements
Redis Cluster
Some aspects of our abstraction for Redis Cluster have been dramatically improved or fixed while others (such as silent handling of connection failures) will be addressed in later patch releases.
- The
ASKING
command is now correctly sent automatically upon-ASK
redirections. - Updated slots maps can be fetched from nodes thanks to the
CLUSTER NODES
command. By default this is a manual operation but it can be enabled to get automatically done upon-MOVED
redirections. - It is possible to specify a common set of connection parameters that are applied to connections created on the fly upon redirections to nodes that are not part of the initial pool.
Query string parsing for connection parameters
URI parsing now relies on parse_str
for the query string part which has a slightly smaller overhead when the number of fields in the querystring grows. Furthermore:
- Parsing does not break when value of a field contains one or more
=
. - Repeated fieldnames using
[]
produce an array of values. - Empty or incomplete
key=value
pairs result in an empty string forkey
.
Deprecations
A couple of methods of Predis\Client
are now marked as deprecated and will be removed in the next major release:
Predis\Client::multiExec()
: superseded byPredis\Client::transaction()
.Predis\Client::pubSub()
: superseded byPredis\Client::pubSubLoop()
. This change was needed due to the recently introducedPUBSUB
command in Redis 2.8.
Future development
Aside from a few more tweaks aimed at improving support for the upcoming Redis Cluster there is not much to add or change in the current v0.8
branch. The library is very stable judging by the history of issues opened during the last months so you can expect a couple of patch releases for v0.8
until Redis 3.0 but nothing more. The good news is that the release of the next major version is imminent and Predis will finally hit v1.0
! The transition from v0.8
to v1.0
will bring a lot of breaking changes required to polish the API of the library and its internals, but the actual impact on your code (that is, if you plan to upgrade) may vary depending on your kind of usage: in simple scenarios where Predis is used as a mere client without relying on its extensibility, it is pretty much possible that nothing will change for you.
You can already start playing with it by requiring "predis/predis": "dev-master"
in composer.json
. Predis v1.0.0 is planned to be released on the same day of the first beta of Redis Cluster, 10th February 2014.
Additional notes
Downloads
Predis v0.8.4
This is a maintenance release for the 0.8 series shipping mostly bug fixes. What follows is an overview of the changes and bug fixes introduced in this new release, details are also available in the CHANGELOG.
Bug fixes and changes
Redis commands
- Added
DUMP
andRESTORE
to the server profile for Redis v2.6. (see related issue) - Fixed
HMSET
to work with cluster, this bug was apparently introduced in Predis v0.8.0. (see related issue) - Modified
ZRANGE
,ZREVRANGE
,ZRANGEBYSCORE
andZREVRANGEBYSCORE
to effectively use theWITHSCORE
modifier only when the value of the option passed to the command isTRUE
. (see related pull request)
Scripted commands and key prefixing
Predis failed to handle falling back from EVALSHA
to EVAL
using scripted commands with no arguments defined for KEYS[]
when the client was configured to use key prefixing. (see related pull request)
Failing host reported in exception messages
When a connection error occurs, such as when Predis is not able to connect to a server, the exception message now includes the incriminated Redis server: Connection refused [tcp://127.0.0.1:3322]
. This can be handy to debug or log errors especially when using multiple nodes in a replication or cluster configuration. (see related pull request)
DispatcherLoop
The pub/sub-based DispatcherLoop class has been fixed to properly work when using a prefixed client instance. (see related pull request)
PhpiredisConnection
This connection backend now uses gethostbynamel to handle hostnames with multiple IP addresses associated and randomly choses one of them. This is mostly useful to distribute the load on multiple Redis instances configured as read-only slaves sitting behind one single hostname. (see related pull request)
Additional notes
Downloads
Predis v0.8.3
Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.
This is a maintenance release for the 0.8 series shipping some new features and minor micro-optimizations. What follows is an overview of the new features and changes introduced in this new release, for a more in-depth list of changes please see the CHANGELOG.
New features and changes
CLIENT SETNAME and CLIENT GETNAME
Thanks to Raphael Stolt's pull request you can now use CLIENT SETNAME
and CLIENT GETNAME
.
New stream-based phpiredis connection backend
We've had a connection backend based on the phpiredis extension for quite some time now, but it required the socket
extension to be loaded in order to work. Now there's a new connection backend which still relies on phpiredis to parse and serialize the Redis protocol, but internally uses PHP's native streams. One of the benefits of using streams is that they support persistent connections when used with plain FastCGI or php-fpm processes. Client configuration to make use of this connection backend is the same as usual, you just need to specify the Predis\Connection\PhpiredisStreamConnection
class:
<?php
$client = new Predis\Client('tcp://127.0.0.1', array(
'connections' => array(
'tcp' => 'Predis\Connection\PhpiredisStreamConnection',
'unix' => 'Predis\Connection\PhpiredisStreamConnection',
),
);
TCP_NODELAY with stream-based connections (PHP >= 5.4.0 only)
One of the historic downsides of using stream-wrapped sockets has always been the impossibility of tinkering with socket options, but luckily for us the introduction of socket_import_stream() in PHP 5.4 removed this limitation. This make it possible to set the TCP_NODELAY
socket option to enable or disable Nagle's algorithm using the tcp_nodelay
connection parameter:
<?php
$client = new Predis\Client('tcp://127.0.0.1?tcp_nodelay=0');
You can effectively set any kind of socket option by yourself in your library or application's code with something like:
<?php
$client = new Predis\Client('tcp://127.0.0.1');
$socket = socket_import_stream($client->getConnection()->getResource());
socket_set_option($socket, SOL_TCP, TCP_NODELAY, 0);
Callable objects for$parameters
in client constructor
Additionally to strings, arrays or even instances of Predis\Connection\ConnectionInterface
, now the first argument of Predis\Client::__construct()
can accept callable objects returning instances of Predis\Connection\ConnectionInterface
. This may appear as an unnecessary addition, but it can reveal itself useful to create custom and self-contained solutions to handle complex configuration scenarios. As an (admittedly) extreme example, we relied on this feature to wrap the code needed to use client-side sharding to distribute keys among virtual nodes of replicated Redis instances without further changing the library's code.
Minor non-breaking change in Lua scripting abstraction
When instructing scripted commands to use all the arguments to populate the ARGV
table and leave KEYS
empty on Lua's side, developers were required to return FALSE
(strictly boolean) from getKeysCount()
in their command implementation. This choice didn't make much sense and now you can simply return 0
. This change does not break existing code since 0 == FALSE
in PHP.
Changes in redis-cluster distribution
Salvatore recently started working again on redis-cluster (that alone is an awesome news!) and commited a change raising the number of hash slots used for distribution, from 4096 to 16384. Our aggregated connection for redis-cluster has been updated accordingly, so pay attention when upgrading both Redis and Predis if you were brave enough having something based on it.
Additional notes
Downloads
Useful links
Predis v0.8.2
Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.
This is a maintenance release for the 0.8 series. What follows is an overview of the new features and fixes introduced in this new release, for a more in-depth list of changes please see the CHANGELOG.
New features and changes
Fix for response parsing in pipelines
The main reason for this new patch release is to fix a bug introduced right before releasing v0.8.0 that prevented complex responses from Redis from being parsed correctly in command pipelines as reported on this issue. This bug didn't affect correctness of the data stored or returned by Redis, but prevented replies to certain commands such as HGETALL from being parsed by the client before returning to the user's code.
Predis-based session handler
A new class Predis\Session\SessionHandler has been added to provide an easy way to use Predis as a backend to store PHP's sessions on Redis. This new class is mainly intended for PHP >= 5.4 since it implements SessionHandlerInterface but it can be used with PHP 5.3 if a polyfill for this interface is provided by you or an external package in your dependencies (such as symfony/http-foundation just to name one).
<?php
$client = new Predis\Client('tcp://127.0.0.1', array('prefix' => 'sessions:'));
$handler = new Predis\Session\SessionHandler($client);
$handler->register();
See a more exhaustive example.
Predis service provider for Silex
Along with this release, the official service provider for Silex has been finally updated to use Predis v0.8 with a new version bump that brings some breaking changes when dealing with multiple clients configuration. These changes was necessary to better fit with the boot mechanism for service providers that was introduced a few months ago in Silex.
Additional notes
Downloads
Useful links
Predis v0.8.1
Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.
This is a maintenance release for the 0.8 series. What follows is an overview of the new features and fixes introduced in this new release, for a more in-depth list of changes please see the CHANGELOG.
New features and changes
Client options
When using callables with client options accepting them, Predis now passes the current option instance as their second argument making it possible to get the default value for that option:
<?php
$options = array(
'profile' => function ($options, $option) {
$profile = $option->getDefault($options);
$profile->defineCommand('test', 'My\Command\TestCommand');
return $profile;
},
);
$client = new Predis\Client('tcp://127.0.0.1', $options);
Now you can use a callable with the connections
option to initialize the instance of Predis\Connection\ConnectionFactoryInterface
that will be used internally by the client to create the underlying connection:
<?php
$options = array(
'connections' => function ($options, $option) {
$factory = $option->getDefault($options);
if (extension_loaded('phpiredis')) {
$factory->define('tcp', 'Predis\Connection\PhpiredisConnection');
$factory->define('unix', 'Predis\Connection\PhpiredisConnection');
}
return $factory.
},
);
Client-side sharding based on node alias
There was this long-standing feature request that never got a decent solution shipped within the library in order to support named connections (distribution of nodes is based on their alias instead of the host:port
pair), but now we have a generalized way to do that supported by both Predis\Cluster\Distribution\HashRing
and Predis\Cluster\Distribution\KetamaPureRing
and consists of passing a callable to the second argument of their constructors:
<?php
use Predis\Cluster\Distribution\HashRing;
use Predis\Connection\PredisCluster;
$options = array(
'cluster' => function ($options) {
$replicas = HashRing::DEFAULT_REPLICAS;
$nodehash = function ($connection) {
return $connection->getParameters()->alias;
}
$hashring = new HashRing($replicas, $nodehash);
$cluster = new PredisCluster($hashring);
return $cluster;
},
);
As you can see you can decide which kind of value to return from your callback, but keep in mind that everything will be casted to string
by our hashring implementation.
Fix for edge case in Lua scripting abstraction
When leveraging the scripted commands abstraction Predis always tries to optimize things by using EVALSHA which, on the other hand, could fail with a -NOSCRIPT
error if the Lua script referred by its SHA1 hash has not been cached by Redis yet. In these cases Predis automatically retries by issuing an EVAL command with the same arguments in addition to the whole Lua script body, but due to this bug the client wasn't using the original parseResponse()
method from the initial command instance to parse the response.
Documentation
Thanks to dominics' initial push we have finally started with the long-overdue task of documenting Predis using Sphinx. Documentation is being written and integrated into our separate documentation branch, so make sure to open your pull requests against this branch if you plan to contribute.
Phpiredis extension
Thanks to the work of seppo0010 we were able to add the support for a PHP extension to parse the Redis protocol in a more efficient way since Predis v0.7.0, but now that the ownership of the phpiredis repository has been transferred to me I plan to tweak it and add new features from time to time (though the idea is to keep it minimal and simple). Having said that, I am by no means a C developer so help and contributions will be highly welcome and appreciated!
Additional notes
Downloads
Useful links
Predis v0.8.0
Predis is a flexible and feature-complete PHP (>= 5.3.2) client library for Redis.
This is a major release and it is not backwards compatible with the v0.7.x series due to the fact that some namespaces and classes have been renamed or moved and a few parameters and client options have been modified. What follows is an overview of the new features and major changes introduced with this new release, for a more in-depth list of changes please read the CHANGELOG.
New features and changes
Support for Redis versions and features
The default server profile is now 2.6
which is the current stable branch of Redis while the dev
profile targets Redis 2.8. Please note that starting with Redis 2.6 the output of INFO
is splitted into sections and, to accomodate this change, Predis returns nested named arrays when using the 2.6
profile.
Connection parameters and client options
There are some changes for connection parameters.
connection_async
is nowasync_connect
connection_timeout
is nowtimeout
connection_persistent
is nowpersistent
throw_errors
has been removed, replaced by the newexceptions
client option.
Please note that using the old parameter names with this new version does not raise any notice.
As an example, the following client configuration for Predis v0.7.x:
$parameters = "tcp://127.0.0.1?connection_async=1&connection_timeout=5&connection_persistent=1&throw_errors=1";
$client = new Predis\Client($parameters);
starting with Predis v0.8.0 must be changed into:
$parameters = "tcp://127.0.0.1?async_connect=1&timeout=5&persistent=1"
$client = new Predis\Client($parameters, array('exceptions' => true));
Additionally, the second parameter of the constructor of Predis\Client
does not accept strings or instances of Predis\Profile\ServerProfileInterface
like in the past but the server profile must be set by using the profile
client option explicitly:
$client = new Predis\Client('tcp://127.0.0.1', '2.4'); // Wrong
$client = new Predis\Client('tcp://127.0.0.1', array('profile' => '2.4')); // OK
Redis Cluster
While redis-cluster will not be available until Redis 3.0, Predis already ships with a first working implementation of the logic needed to use this amazing new feature. Configuring the client is simply a matter of passing the list of nodes in the same exact order as they are specified when using redis-trib
and setting the cluster
client option to redis
:
$nodes = array('tcp://10.0.0.1', 'tcp://10.0.0.2', 'tcp://10.0.0.3');
$client = new Predis\Client($nodes, array('cluster' => 'redis'));
Obviously you can rest assured that the good old way of creating a cluster of Redis nodes simply by relying on client-side sharding is still in place and is the default behavior of the client.
Server-side scripting with Lua
Predis supported Redis scripting since v0.7.0 but our high-level abstraction built on top of EVAL
and EVALSHA
(we call it a scripted command) has been improved to save bandwidth by using the latter by default and falling back transparently to the former when required (that is, when Redis replies to EVALSHA
with a -NOSCRIPT
error).
Going asynchronous with Predis\Async
Crazy? Maybe, but at least now you can thanks to Predis\Async. This separate project shares the same style and feel of Predis by reusing some of its core classes and is built on top of React to provide a fully-asynchronous implementation of a Redis client. The library is considered experimental and subject to changes in its API, but it already works and can cooperate seamlessy with any other library that makes use of the core event loop abstraction provided by React/EventLoop.
Future development
While this new major release admittedly do not add much features to the plate aside from early support for redis-cluster and a separate project for a fully-asynchronous client, the internals of Predis have been extensively reworked to make the library and its core parts even more easy to extend and reuse, but also with some optimizations put in place. We are at a point in which further changes to the internal architecture of Predis should not be needed for a while, or at least not until we decide to drop compatibility with PHP 5.3 and rewrite stuff to make use of new features introduced in PHP 5.4, which means that we can proceed with experimenting a few ideas such as having core parts of the library implemented in C as an optional PHP extension. Right now you can already use phpiredis to speed thins up, but we can definitely do better that that.
In a more immediate future, aside from addressing eventual bugs the next patch releases in the v0.8.x series will also see the addition of some missing features such as an abstration to deal with redis-sentinel.
Additional notes
Downloads
Useful links
Predis v0.7.3
Predis is a flexible and feature-complete PHP client library for Redis.
This is a maintenance release for the 0.7 series. What follows is an overview of the new features introduced in this new release. For a more in-depth list of changes please see the CHANGELOG.
New features and changes
New commands in the Redis 2.6 server profile
Two new commands have been added to Redis 2.6: BITOP
and BITCOUNT
.
Scripting abstraction improvements
It is now possible to use negative numbers in the getKeysCount()
method to tell Predis\Commands\ScriptedCommand
to calculate the actual number of keys used to populate the KEYS
array for EVAL
starting from the end of the arguments list. You can read this comment for a description of a use case.
We also fixed a bug in Predis\Commands\ServerEvalSHA::getScriptHash()
.
Additional notes
Downloads
Related projects
- SncRedisBundle for Symfony2.
- PredisServiceProvider for Silex.
Useful links
Predis v0.7.2
Predis is a flexible and feature-complete PHP client library for Redis.
This is a maintenance release for the 0.7 series. What follows is an overview of the new features introduced in this new release. For a more in-depth list of changes please see the CHANGELOG..
New features and changes
New server profile for Redis 2.6
While 2.4
is still the default server profile, you can now use 2.6
instead of dev
to use the new commands and features (such as scripting) implemented in Redis 2.6:
$client = new Predis\Client('tcp://127.0.0.1', array('profile' => '2.6'));
The dev
profile will target Redis 2.8
.
MONITOR and Redis 2.6
The output of MONITOR
in Redis 2.6 has been slightly changed resulting in the inability for Predis\MonitorContext
to work properly. Now Predis can handle the new output automatically and will add the client
field to the returned message object when connected to Redis >= 2.6.
Serializable connections
Connection instances can be serialized and unserialized using serialize()
and unserialize()
. While probably not useful in most scenarios, this can be handy for example with client-side clustering or replication to lower the overhead of initializing a connection object with many sub-connections since unserializing them can be up to 5x times faster.
$client1 = new Predis\Client();
$serializedConnection = serialize($client->getConnection());
$unserializedConnection = unserialize($serializedConnection);
$client2 = new Predis\Client($unserializedConnection);
Additional notes
Downloads
Related projects
- SncRedisBundle for Symfony2.
- PredisServiceProvider for Silex.
Useful links
Predis v0.7.1
Predis is a flexible and feature-complete PHP client library for Redis.
This is a maintenance release for the 0.7 series that fixes some minor glitches and adds a couple of new features. What follows is an overview of the new features introduced in this new release. For a more in-depth list of changes please see the CHANGELOG..
New features and changes
New PEAR channel
We still want to have PEAR as one of the methods to distribute Predis, but unfortunately PearHub seems to be unmaintained and the generation of new PEAR packages is currently stuck. To overcome this issue we set up a new PEAR channel that will host past and future releases of Predis.
Master / slave replication
This one has been a long-standing feature request but master / slave replication configurations are now supported at client level, which means that it is now possible to configure a group of connections with one master server and one or more slave servers. Commands performing read operations (such as GET
) are executed against one of the slaves and the client switches to the master only upon commands performing write operations (such as SET
). The configuration of a new client instance for replication is easy, just set the replication
client option to true
and specify at least two connections, with one of them being the master (see alias=master
):
$parameters = array(
'tcp://127.0.0.1:6379?alias=master',
'tcp://127.0.0.1:6380?alias=slave1',
);
$options = array('replication' => true);
$client = new Predis\Client($parameters, $options);
Redis transactions (MULTI
/ EXEC
) force the client to switch to the master server even when the transaction contains read-only operations. The same applies to pipelines, but in this case it is is an implementation detail that could change in future releases.
EVAL
and EVALSHA
are considered write commands by default since it is not possible for the client to know when a script performs read-only operations or not. Developers can still override this behaviour on a script-basis with a slightly more complex configuration using the replication
client option:
$options = array(
'replication' => function() {
$replication = new Predis\Network\MasterSlaveReplication();
$replication->setScriptReadOnly("return redis.call('GET', KEYS[1])");
return $replication;
},
);
You can see this example for a complete script using a simple configuration and this one for a more complex one.
Additional notes
Downloads
Related projects
- SncRedisBundle for Symfony2.
- PredisServiceProvider for Silex.