List of changes:
- The cluster connection sends an ASKING command before retrying
a command on a different node when Redis returns a -ASK response.
- The cluster connection can be initialized with a partial list of
nodes, the full slots map will be fetched from Redis itself using
the CLUSTER NODES command.
- The slots map can be optionally retrieved from Redis if the server
returns a -MOVE response, otherwise only the interested slot will
be permanently reassigned to the new target node.
- It is possible to specify a set of common parameters applied to
connections created on the fly when not part of the current pool
upon -MOVE and -ASK responses returned by Redis for redirections.
- $cluster->connect() connects to a random connection in the pool
instead of forcing the connect operation on all the connections.
By raw we mean that input arguments are not filtered and responses are
not parsed, which means arguments must follow the command signature as
defined by Redis and complex responses are left untouched.
When instantiating an instance of `Predis\Command\RawCommand` you must
pass at least the command ID. You can pass further arguments in the
array or you can just set them later with `RawCommand::setArguments()`
but you cannot modify the command ID once instantiated.
$command = new Predis\Command\RawCommand(['SET', 'foo', 'bar']);
$response = $client->executeCommand($command);
While higher level abstractions built upon `Predis\Client` should just
use commands created by the profile in use, inner parts of the library
might use raw commands to provide certain functionalities making sure
that input and output of commands are always consistent, independent
of the profile.
NOTE: Backported from v0.9.
The main reason behind that code duplication was performance related
as we tried to reduce method calls when possible, even at the cost of
falling into the realm of early optimizations. Apparently we just lose
~400 req/sec on a 21000 req/sec basis ("SET foo bar") using PHP 5.5.3
(packaged by Ubuntu 13.10) on an Intel Q6600, so we will most likely
stick with this change for the sake of best practices.
Backported from v0.9-dev.
This iterator tries to mimic the same behaviour of the cursor-based
iterators implemented upon the SCAN family of commands and offering
only limited guarantees on the returned elements, but uses LRANGE to
fetch items from a list incrementally.
We are experimenting with a new approach at naming classes using less
redundant names by leveraging the containing namespace. The PHP "use"
directive is not limited to class names but can be used to import the
whole namespace, which means you can do something like this:
use Predis\Collection\Iterator;
// ...
foreach (new Iterator\Keyspace($client) as $key) {
// ...
}
Alternatively you can always rely on "use ... as ..." to import one of
the classes by giving it a more meaningful name in the context of the
root namespace:
use Predis\Collection\Iterator\Keyspace as KeyspaceIterator;
// ...
foreach (new KeyspaceIterator($client) as $key) {
// ...
}
In this specific case we chose to apply the -Key postfix to classes
iterating Redis keys to be more explicit about the fact that those
iterators does not work on local in-memory collections, but fetch
items from a key stored on a remote Redis server.
This iterator allows to perform full iterations over fields and values of a
hash by wrapping the incremental nature of HSCAN just like we did for SCAN:
$client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
$iterator = new Predis\Iterator\Scan\HashIterator($client, "hash_key");
foreach ($iterator as $field => $value) {
echo "$field => $value" . PHP_EOL;
}
Being HSCAN closely related to SCAN, it is subject to the same behaviour,
see http://redis.io/commands/scan for reference.
This iterator allows to perform full iterations over the members of a sorted
set by wrapping the incremental nature of ZSCAN just like we did for SCAN:
$client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
$iterator = new Predis\Iterator\Scan\SortedSetIterator($client, "zset_key");
foreach ($iterator as $member => $rank) {
echo "$rank => $member" . PHP_EOL;
}
Being ZSCAN closely related to SCAN, it is subject to the same behaviour,
see http://redis.io/commands/scan for reference.
This iterator implementation returns the member as key and the rank as value
since the rank is a float value which would be truncated when transforming
the iteration to an array (e.g. using iterator_to_array()). Luckily PHP
preserves the insertion order for named arrays members still result sorted.
This iterator allows to perform full iterations over the members of a set
by wrapping the incremental nature of SSCAN just like we did for SCAN:
$client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
$iterator = new Predis\Iterator\Scan\SetIterator($client, "set_key");
foreach ($iterator as $member) {
echo $member . PHP_EOL;
}
Being SSCAN closely related to SCAN, it is subject to the same behaviour,
see http://redis.io/commands/scan for reference.
Meh
The iterators based on SCAN, SSCAN, ZSCAN and HSCAN will extend this abstract
class to share most of the logic which is common for all of the Redis commands
in the SCAN family.
This iterator allows to perform full iterations over the keyspace of a Redis
instance by wrapping the incremental nature of SCAN using an abstraction that
fits perfectly in userland code:
$client = new Predis\Client('tcp://127.0.0.1', ['profile' => '2.8']);
$iterator = new Predis\Iterator\Scan\KeyspaceIterator($client);
foreach ($iterator as $key) {
echo $key . PHP_EOL;
}
Memory consumption during an iteration is limited because elements are fetched
incrementally, on the other hand SCAN gives limited guarantees about returned
elements since the underlying collection (the keyspace in this case) can change
during the whole iteration process. The most immediate drawback is that the same
element may be returned multiple times.
See http://redis.io/commands/scan to fully understand the inner workings,
and particularly the "Scan guarantees" paragraph.
Client::pubSub() still works like usual by returning a new pub/sub
context, but it is now considered an alias of Client::pubSubLoop().
This change is necessary in preparation for the next major version
of Predis where Client::pubSub() will be used for the new PUBSUB
command introduced in Redis 2.8.
One test is currently marked as skipped because it makes
Redis crash when the specified MATCH pattern returns one
or more elements.
See http://redis.io/commands/scan for reference.
One test is currently marked as skipped because it makes
Redis crash when the specified MATCH pattern returns one
or more elements.
See http://redis.io/commands/scan for reference.
We still need to populate this new server profile with the
recently added new commands for Redis 2.8.
The next development version has been set to Redis 3.0.
Using gethostbyname, we will reuse the same (first) IP address for
each request. Here, we choose the IP we use randomly.
This is practical in a case where we have multiple redis read-only
slaves that can't invidually support the full application load, but are
accessible through a single hostname.
Providing a basic hint in the exception message about the server that caused
a connection exception could be useful especially with aggregated connections.
This is in response to issue #110.
A missing "use" directive was preventing the hash strategy to properly
use the specific methods of Predis\Command\ScriptedCommand, falling back
to analyzing the raw arguments array of the command.
Actually this was already the case for certain commands, but some of them
was left unguarded for such cases. This commit also fixes#109.
The behaviour of silently skipping key prefixing when a command has no
arguments may change in the future so we added explicit tests as guards
for future changes. Predis\Command\Processor\KeyPrefixProcessor will
continue to skip key prefixing on empty arguments, regardless.