Predis Versions Save

A flexible and feature-complete Redis client for PHP.

v1.1.3

3 years ago
  • Ensure compatibility with PHP 8.
  • Moved repository from github.com/nrk/predis to github.com/predis/predis.
  • FIX: Moved cweagans/composer-patches dependency to require-dev.
  • FIX: Include PHPUnit .patch files in exports.

v1.1.2

3 years ago

Predis is under new management. Read the announcement and checkout the roadmap 🚀

If you (or your business) would like to support the development of this fantastic library and ensure it's bright future, please use the GitHub Sponsor button 🙏🏻

Changes

  • FIX: pure CRC16 implementation failed to calculate the correct hash when the input value passed to the hash() method is an integer (PR #450).
  • FIX: make PHP iterator abstractions for ZSCAN and HSCAN working with PHP 7.2 due to a breaking change, namely the removal of each() (PR #448).

v1.1.1

7 years ago

This is a patch release of Predis v1.1 that fixes a few bugs affecting the previous release. As usual you can read the CHANGELOG for a schematic list of the changes.

Bug fixes

  • FIX: password and database from the global parameters client option were still being applied to sentinels connections making them fail (sentinels do not understand the AUTH and SELECT commands) (PR #346).
  • FIX: when a sentinel instance reports no slave for a service, invoking connect() on the redis-sentinel connection backend should fall back to the master connection instead of failing (ISSUE #342).
  • FIX: the two connection backends based on ext-phpiredis has some kind of issues with the GC and the internal use of closures as reader callbacks that prevented connections going out of scope from being properly collected and the underlying stream or socket resources from being closed and freed. This should not have had any actual effect in real-world scenarios due to the lifecycle of PHP scripts, but we fixed it anyway (ISSUE #345).

v1.1.0

7 years ago

Introduction

This is a minor release of Predis packed with new features and various improvements of existing ones. As usual you can read the CHANGELOG for a schematic list of the changes. Thanks to anyone who provided feedback, especially on the new features, and proposed changes implemented in this release! Starting today we also have a chat room on Gitter, for now it's kind of an experiment but we'll see on the long run if it'll prove to be useful.

IMPORTANT: if you are using "predis/predis": "dev-master" in composer.json then replace the requirement with tagged releases in the v1.1 branch as soon as possible! Starting today the master branch will host the development of the next major version of Predis, the first few commits containing some major breaking changes will land there in a matter of days meaning that if you won't replace dev-master your applications may (and most likely will) fail all of sudden.

NOTE: speaking of Predis v2.0 we are aiming to bump the minimum required version of PHP to 5.5.9 (most likely to happen) and drop PEAR for distribution (still to be decided). The v1.1 branch will be maintaned for fixes so if you are stuck with PHP 5.3 and 5.4 you don't have too much to worry about for a while. If you have anything to say on the matter please join the discussion by leaving a comment or a reaction on #335, we need your feedback!

New features

  • Support for redis-sentinel is finally baked into Predis! As usual configuring the client is easy, it's just a matter of providing a list of sentinel servers and configure the client accordingly:

    $parameters = ['tcp://127.0.0.1:5380', 'tcp://127.0.0.1:5381', 'tcp://127.0.0.1:5382'];
    
    $options = [
        'replication' => 'sentinel', // use the appropriate replication backend
        'service' => 'mymaster',     // provide a service name for discovery
    ];
    
    $client = new Predis\Client($parameters, $options);
    

    See replication_sentinel.php for a complete example.

  • Redis servers protected by SSL-encrypted connections can be accessed by using the tls or rediss scheme in connection parameters along with SSL-specific options in the ssl parameter (array):

    // Parameters in the form of a named array
    $parameters = [
        'scheme' => 'tls',
        'host'   => '127.0.0.1',
        'ssl'    => [
            'cafile' => '/path/to/redis.pem',
            'verify_peer_name' => true,
        ],
    ];
    
    // Parameters in the form of an URI string
    $parameters = 'tls://127.0.0.1?ssl[cafile]=/path/to/redis.pem&ssl[verify_peer_name]=1';
    
  • Implemented the ability to specify default connection parameters for aggregate connections with the new parameters client option. These parameters augment the usual user-supplied connection parameters (but do not take the precedence over them) when creating new connections and they are mostly useful when the client is using aggregate connections such as redis-cluster and redis-sentinel as these backends can create new connections on the fly based on responses and redirections from Redis:

    $parameters = ['tcp://127.0.0.1:6381', 'tcp://127.0.0.1:6382', 'tcp://127.0.0.1:6383'];
    
    $options = [
        'cluster' => 'redis',
        // New connections to Redis will be created using the same following parameters:
        'parameters' => ['database' => 5, 'password' => $secret],
    ];
    
    $client = new Predis\Client($parameters, $options);
    
  • Predis\Client implements the IteratorAggregate interface making it is possible to iterate over traversable aggregate connections and get a new client instance for each Redis node:

    $client = new Predis\Client($parameters, ['cluster' => 'redis']);
    
    foreach ($client as $nodeClient) {
        $nodeClient->flushdb();  // executes FLUSHDB on each node of the cluster
    }
    

Changes

  • The default server profile for the client now targets Redis 3.2.
  • Responses to the following list of commands are not casted into booleans anymore but instead the original integer value of the response is returned: SETNX, MSETNX, SMOVE, SISMEMBER, HSET, HSETNX, HEXISTS, PFADD, EXISTS, MOVE, PERSIST, EXPIRE, EXPIREAT, RENAMENX. This change does not have a significant impact unless when using strict comparisons (=== and !==) on the returned value.
  • Using unix:///path/to/socket in URI strings to specify a UNIX domain socket file is now deprecated in favor of the format unix:/path/to/socket (note the lack of the double slash after the scheme) and will not be supported starting with the next major release.
  • The client throws exceptions when Redis returns any kind of error response to initialization commands (the ones being automatically sent when a connection is established, such as SELECT and AUTH when database and password are set in connection parameters) regardless of the value of the exception option.
  • Iterating over an instance of Predis\Connection\Aggregate\RedisCluster will return all the connections mapped in the slots map instead of just the ones in the in-memory pool. This change makes it possible, when the slots map is retrieved from Redis, to iterate over all of the master nodes in the cluster. When the use of CLUSTER SLOTS is disabled via the useClusterSlots() method, the iteration returns only the connections with slots ranges associated in their parameters or the ones initialized by -MOVED responses in order to make the behaviour of the iteration consistent between the two modes of operation.

Improvements

  • Non-boolean string values passed to the persistent connection parameter can be used to create different persistent connections to the same host-port pair:

    // $parameters1 and $parameters2 will create two different persistent connections:
    $parameters1 = "tcp://127.0.0.1:6379?persistent=first";
    $parameters2 = "tcp://127.0.0.1:6379?persistent=second";
    

    Note that this feature was already present in Predis but required both persistent and path to be set as illustrated by #139, this change was needed to prevent confusion with how path is used to select a database when using the redis scheme.

  • Various improvements to Predis\Connection\Aggregate\MasterSlaveReplication (the "basic" replication backend, not the new one based on redis-sentinel):

    • When the client is not able to send a read-only command to a slave because the current connection fails or the slave is resyncing (-LOADING response returned by Redis), the backend discards the failed connection and performs a new attempt on the next slave. When no other slave is available the master server is used for read-only commands as last resort.
    • It is possible to discover the current replication configuration on the fly by invoking the discover() method which internally relies on the output of the command INFO REPLICATION executed against the master server or one of the slaves. The backend can also be configured to do this automatically when it fails to reach one of the servers.
    • Implemented the switchToMaster() and switchToSlave() methods to make it easier to force a switch to the master server or a random slave when needed.

v1.0.0

7 years ago

This is not only a new and major release of Predis, but it is an important milestone because it represents the first stable release in terms of API (both public and internal). Lots of changes have been made to improve the overall design and code quality while optimizing the library as much as possible.

You can consult the CHANGELOG for more details about changes and bug fixes introduced in this release.

IMPORTANT NOTE: we switched to PSR-4 for autoloading but PEAR packaging still uses PSR-0 for obvious reasons, the conversion is performed when generating the package using bin/create-pear. We do not plan to support installation through PEAR indefinitely, but we will stick with it for a few more releases.

Introduction

One of the purposes of this new release was to make use of better names for classes, interfaces and namespaces so we ended up with shorter fully-qualified names and a better organization of namespaces. While these changes can be quite radical in certain cases, the truth is that they will most likely affect only code-bases where developers made use of certain classes to extend the library with custom features. Those simply using Predis as a client will not probably notice any difference. Just to make a few examples (for the rest, see the CHANGELOG):

  • The Predis\Option namespace is now Predis\Configuration.
  • The Predis\Command\AbstractCommand class is now Predis\Command\Command.
  • The Predis\Command\ScriptedCommand class is now Predis\Command\ScriptCommand.
  • Aggregate connections (cluster, replication) are in the Predis\Connection\Aggregate namespace.
  • Classes representing status and error responses are in the Predis\Response namespace.

Obviously it is not only a matter of renaming or moving things around, the overall internal design of Predis has been dramatically improved and now certain aspects of the library (such as clustering) are more solid and more open to extension. Last but not least a lot of work has been done to keep performances in check, resulting in less overhead when initializing client instances and no difference at runtime in raw numbers compared to v0.8.x despite the additional flexibility.

Improvements

  • @method in docblocks: while this is not strictly a feature, now Predis ships with @method tags for Predis\ClientInterface and Predis\ClientContextInterface (pipelines, transactions) so you can leverage autocompletion and inspection while coding with your favourite IDE. This should be a much welcome addition for many developers since it has been requested many times in the last couple of years.

  • Server profiles: the default one is now 3.0 (obviously targeting Redis 3.0.0). It is safe to switch now since the are no breaking changes between Redis 2.8 and 3.0. At the same time, the server profile for Redis 1.2 has been removed since it is relatively ancient stuff.

  • New commands: added SENTINEL to the server profile for Redis 2.6 and PUBSUB to the server profile for Redis 2.8. Please note that you will not find CLUSTER and other commands used by redis-cluster in the server profile for Redis 3.0. Internally they are used as raw commands, they may be added in the future though as soon as Redis 3.0 becomes stable.

  • Raw commands: now they can be sent simply by providing an array of arguments (comprising of the command ID) to Predis\Client::executeRaw(). This method skips key prefixing (and more generally, any command processor) and response parsing, so it always returns responses as documented on the Redis website. It is also possible to tell when Redis returns an error thanks to the second optional argument populated by reference with a boolean value:

    $response = $client->executeRaw(["SET", "foo", "bar"]); // string(2) "OK"
    $response = $client->executeRaw(["STRLEN", "foo"]);     // int(3)
    
    // When $iserror is TRUE, $response contains the error string.
    $response = $client->executeRaw(["LPUSH", "foo", "bar"], &$iserror);
    
  • Changes for ZRANGE-like commands using WITHSCORES: Predis used to return the member and score pair as an array of [$member, $score] when using the WITHSCORES modifier with ZRANGE, ZREVRANGE, ZRANGEBYSCORE and ZREVRANGEBYSCORE. Now the raw response is parsed to a named array so members and their scores can be accessed as $member => $score.

    $members = $client->zrange("key", 0, -1, "withscores");
    // Predis v0.8 (old): [["member1", "score1"], ...]
    // Predis v1.0 (new): ["member1" => "score1", ...]
    

    The output of ZSCAN has also been changed accordingly in order to reflect the same output, while Predis\Collection\Iterator\SortedSetKey is not affected by this change. NOTE: the ordering of the original response is still preserved thanks to how PHP internally works with named arrays.

  • Redis responses: status responses are now returned as instances of Predis\Response\Status and carry their original payload string. +OK is then no more returned to the client as a boolean TRUE, but since a status response can be transparently casted to string one can do $response == "OK" which is also more akin to how Redis replies to clients. Instances of common status responses such as +OK or +QUEUED are shared internally in order to avoid wasting memory. Another change regards custom response parsers in commands (see Predis\Command\CommandInterface::parseResponse()) which are now applied inside consumer classes such as Predis\Client.

  • Client options: the fully reworked Predis\Configuration\Options class now has the ability to lazily initialize values using objects that respond to __invoke() and it works even for custom options defined by the user. This is an example of a complex and modular set of options where standard and user-defined options are mixed together, and the ones regarding cluster are initialized lazily only when needed by the client:

    $client = new Predis\Client($parameters, [
      'exceptions'  => true,
      'connections' => [
        'tcp'  => 'Predis\Connection\PhpiredisStreamConnection',
      ],
      'distributor' => function () {
        return new Predis\Cluster\Distributor\KetamaRing();
      },
      'strategy'    => function ($options) {
        return new Predis\Cluster\PredisStrategy($options->distributor);
      },
      'cluster'     => function ($options) {
        $strategy = $options->strategy;
        $cluster = new Predis\Connection\Aggregate\PredisCluster($strategy);
    
        return $cluster;
      },
      'profile'     => function ($options, $option) {
        $profile = $options->getDefault($option);
        $profile->defineCommand("luascript", "Nrk\Command\LuaScriptCommand");
    
        return $profile;
      },
    ]);
    

    In addition to the client options already supported by v0.8, the new aggregate option overrides both cluster and replication and can be used to initialize an aggregate connection taking full control over its initialization (the return type must be Predis\Connection\AggregateConnectionInterface).

  • Cluster with client-side sharding: Predis now uses the same rules defined by the redis-cluster specification when dealing with empty hash-tags {} in keys, so upgrading Predis might affect the distribution of your already-deployed cluster. If you want to make sure that you will not be affected by this change, you can extend Predis\Cluster\PredisStrategy to override the extractKeyTag($key) method and configure the client to use your strategy like this:

    class OldPredisStrategy extends Predis\Cluster\PredisStrategy
    {
      protected function extractKeyTag($key)
      {
        if (false !== $start = strpos($key, '{')) {
          if (false !== $end = strpos($key, '}', $start)) {
            $key = substr($key, ++$start, $end - $start);
          }
        }
    
        return $key;
      }
    }
    
    $client = new Predis\Client($nodes, [
      "cluster" => function () {
        $strategy = new OldPredisStrategy();
        $cluster = new Predis\Connection\Aggregate\PredisCluster($strategy);
    
        return $cluster;
      },
    ]);
    

    This is possible because, starting with v1.0, Predis\Connection\Aggregate\PredisCluster accepts an instance of Predis\Cluster\StrategyInterface as the only argument in its constructor instead of Predis\Cluster\Distributor\DistributorInterface. The distributor, on the other hand, is now wrapped by Predis\Cluster\PredisStrategy.

  • Pipeline options: Predis\Client::pipeline() now accepts options to choose which kind of pipeline object should be initialized among the ones supported by Predis:

    • atomic: wraps the pipeline in a MULTI / EXEC transaction (Predis\Pipeline\Atomic).
    • fire-and-forget: does not read back responses (Predis\Pipeline\FireAndForget).
  • Transaction options: while Predis\Transaction\MultiExec still supports cas, watch and retry, there are also a couple of changes:

    • exceptions: overrides the value of $options->exceptions provided in client options.
    • on_retry: this option has been removed.
  • Key prefixing: while changes in this case are completely transparent to users, the prefixing logic has been moved from command classes to the key prefix processor returned by $options->prefix. Commands are recognized by their IDs and developers can define or override the handlers used to prefix keys based on their arguments. This makes it possible to prefix keys also when using the generic Predis\Command\RawCommand class.

Dropped stuff:

  • Obsolete methods: Predis\Client::multiExec() and Predis\Client::pubSub() have been removed after having been deprecated in v0.8.5. The new names for these methods are respectively Predis\Client::transaction() and Predis\Client::pubSubLoop().
  • Iterable multibulk responses: the commonly used Predis\Connection\StreamConnection does not support them anymore and iterable_multibulk has been removed from the default connection parameters. You can still use them with Predis\Connection\CompositeStreamConnection (it is slower, but makes use of a pluggable protocol system) and the classes implementing multibulk iterators are available in the Predis\Response\Iterator namespace.
  • Pipeline executors: they are no more needed after the changes in Predis\Pipeline\Pipeline.

What's next?

Having finally reached v1.0 is a great milestone considering that Predis has been around for 5 years now, but there is obviously more to come: v1.1 will ship with new features and the most important ones will most likely be support for redis-sentinel with replication and support for slaves in redis-cluster. Minor versions will be released more frequently compared to the past, now that the library is considered stable in terms of design and API.

There is also another aspect that should really be addressed: documentation. Predis simply does not have enough documentation covering useful features or the inner parts of the library. I plan to resume the initial efforts started in the documentation branch but frankly I hope to receive also some external contributions.

All in all I am happy with this release and even though it took 7 months to ship (way more than what I originally planned, mostly due to some busy months) the result is more than satisfactory in terms of quality. Big thanks to everyone who has shared their feedbacks or contributed with suggestions and code!

KTHXBYE.

Downloads

v1.0.4

7 years ago

This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

IMPORTANT: Predis v1.1.0 is going to be released in just a few days, this minor release will ship with various improvements and the much-awaited support for redis-sentinel. Soon after that the master branch will host the development of Predis v2.0 and the first major change will be a bump of the minimum required version of PHP to 5.5.9, please read about it here and leave a comment if you have something to say on the matter as the decision has not been finalized as of yet.

Improvements

  • Added a new profile for Redis 3.2 with its new commands: HSTRLEN, BITFIELD, GEOADD, GEOHASH, GEOPOS, GEODIST, GEORADIUS, GEORADIUSBYMEMBER. The default server profile for Predis is still the one for Redis 3.0 so you must set the profile client option to 3.2 when initializing the client in order to be able to use them when connecting to Redis 3.2.
  • redis-cluster: when the connection to a specific node fails the client tries to connect to another node in order to refresh the slots map and perform a new attempt to execute a command.
  • redis-cluster: connections to nodes can now be preassigned to non-contiguous slot ranges via the slots parameter using a comma separator (e.g. tcp://127.0.0.1:6379?slots=0-5460,5500-5600,11000)

Bug fixes

  • FIX: Predis\Collection\Iterator\HashKey was returning corrupted values when iterating hash keys containing integer fields (PR #330, ISSUE #331).
  • FIX: Predis\Connection\StreamConnection and Predis\Protocol\Text\RequestSerializer do not fail when serializing commands with holes in their arguments (e.g. [0 => 'key:0', 2 => 'key:2']) just like the phpiredis-based connection backends (ISSUE #316).

v1.0.3

8 years ago

This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

IMPORTANT NOTICE: this release supersedes v1.0.2.

Bug fixes

  • FIX: the previous release introduced a severe regression on HHVM preventing the client from connecting to Redis using IPv4 addresses. Code running on the standard PHP interpreter is unaffected. (#269)

v1.0.1

8 years ago

This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

Improvements

  • Added the BITPOS command to the server profile for Redis 2.8 (pull request by @nicchap).
  • It is now possible to specify a timeout for read/write operations also when using UNIX domain sockets with Predis\Connection\StreamConnection which is the default connection class based on PHP's streams (pull request by @srhnsn).

Bug fixes

  • A bug prevented Predis\Collection\Iterator\SortedSetKey to work correctly when iterating over sorted sets containing integer members (see #216).
  • Applied a workaround for a bug in old versions of PHP < 5.3.9 affecting inheritance (see 99f4312a6feb2cadaf83b008d006c1720f580723).
  • Prevent E_NOTICE messages from being emitted when requesting empty or unexistent info sections using INFO.

Notes

  • Due to a bug in HHVM <= 3.4.0, it is not possible to use Predis\PubSub\Consumer and Predis\Monitor\Consumer when running under Facebook's runtime for now. You can find more details in the discussion on #231 (thanks @rubensayshi for the catch!) which also provides an hack to work around this issue until the next release of HHVM will ship with their bug fixed.

Downloads

v1.0.2

8 years ago

This is a maintenance release for the 1.0 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

IMPORTANT NOTICE: this release has been superseded by v1.0.3 due to a severe regression affecting only HHVM preventing the client from connecting to Redis using IPv4 addresses. Code running on the standard PHP interpreter is unaffected.

Improvements

  • IPv6 is fully supported.
  • The redis scheme can be used in URI strings and is considered an alias of tcp but the rules applied when parsing the URI follow the provisional registration document published by IANA while the usual Predis-specific rules still apply when using tcp and other schemes.
  • Implemented some missing commands: HSTRLEN (Redis >= 3.2), ZREVRANGEBYLEX (Redis >= 2.8) and MIGRATE (>= 2.6).
  • The ZADD modifiers NX|XX, CH, INCR introduced in Redis 3.0.2 can also be used with the simplified signature of this command where scores and members are passed as a named array.

Bug fixes

  • FIX: Predis\Configuration\Options must not trigger the autoloader when values are strings (#257).
  • FIX: BITPOS was not defined in the key-prefix processor (#265) and in the replication strategy.

Notes

  • Predis v1.1.0 should follow in just a few weeks and, being a minor release, will deliver more than just bugfixes or minor improvements. The addition of support for redis-sentinel is a long-standing feature request that will hopefully find its way into the library (see #131) and some major and much needed improvements to redis-cluster are also scheduled (see #173). As usual any help is more than appreciated so feel free to hop on these issues for sharing ideas and advices, or even contribute with a pull request.

v0.8.7

9 years ago

This is a maintenance release for the 0.8 series. What follows is an overview of the changes and bug fixes introduced in this release, more details are available in the CHANGELOG.

New features

Redis commands

  • Added the profile alias 3.0 for Redis 3.0, but 2.8 is still the default one.
  • Added COMMAND to the server profile for Redis 2.8. This command is actually available since Redis 2.8.13 so it will return a -ERR when executed against older versions of Redis.

Redis Cluster

The new default for redis-cluster when the client receives a -MOVED response is to fetch an updated slots map automatically from the node target of the persistent redirection. Thanks to this change you can now feed the client constructor with only a few of the nodes in your cluster without the need to use a more complex configuration, so even if your cluster have - let's say - 10 nodes you can still use only a couple or more connection parameters:

$client = new Predis\Client(
    ["tcp://10.0.0.1:6379", "tcp://10.0.0.1:6380"],
    ["cluster" => "redis"]
);

Internally the client fetches the slots map using the new CLUSTER SLOTS command made available since Redis 3.0.0b7, which means your nodes must be upgraded to the most recent beta release of Redis (but you should do it anyway since it is beta software).

PubSub

Implemented PING in our PUB/SUB loop abstraction for Redis >= 3.0.0b8. You can now ping the connection with an optional payload directly from the loop instance, and receive back a PONG message:

foreach ($pubSubLoop as $message) {
    switch ($message->kind) {
        case "subscribe":
            $pubSubLoop->ping("hello!");
            break;

        case "pong":
            echo "Pong message with payload $message->payload\n";
            break;
    }
}

Bug fixes

  • The patch applied in v0.8.6 to fix #180 introduced a regression affecting read/write timeouts in Predis\Connection\PhpiredisStreamConnection so we had to apply a further fix which, unfortunately, absolutely requires PHP 5.4+ meaning that read/write timeouts will be ignored from now on PHP 5.3.

Downloads