This makes it possible to easily assign a connection to a slot range
using the key "slots" in connection parameters like in the following
example:
$parameters = array(
'tcp://127.0.0.1:6379?slots=0-1364',
'tcp://127.0.0.1:6380?slots=1365-2729',
'tcp://127.0.0.1:6381?slots=2730-4095',
);
$options = array('cluster' => 'redis');
$client = new Predis\Client($parameters, $options);
It is possible to get the full list of slot ranges for each node of
the cluster using redis-cli connected to one of the nodes:
./redis-cli -h 127.0.0.1 -p 6379 CLUSTER NODES
The last column in the resulting output contains the slots assigned
to each instance participating to the redis cluster.
This is useful to avoid guessing the correct server instance at runtime
thus reducing the overhead of a guess-and-try approach since relying on
-ASK or -MOVED responses returned by a node is a costly operation.
For now, you can pre-associate slots using the "cluster" client option:
$parameters = array(
'tcp://127.0.0.1:6379',
'tcp://127.0.0.1:6380',
'tcp://127.0.0.1:6381',
);
$options = array(
'cluster' => function ($options) {
$cluster = new Predis\Connection\RedisCluster();
$cluster->setSlots(0, 1364, '127.0.0.1:6379');
$cluster->setSlots(1365, 2729, '127.0.0.1:6380');
$cluster->setSlots(2730, 4095, '127.0.0.1:6381');
return $cluster;
},
);
$client = new Predis\Client($parameters, $options);
In the future we will make the slots configuration easier by fetching
the configuration from a node using the command "CLUSTER NODES" or by
pre-computing the slices of slots associated to a node when adding it
to the cluster connection object.
This is needed because redis-cluster does not support the same commands
or operations that can be performed with our client-side managed predis
cluster.
For example redis-cluster does not support key tagging (that is, parts
of a key enclosed by {...} to hash only that specific part of a key)
and multiple-key operations suchs as MGET, MSET, SDIFF, SUNION or SINTER.
Some multiple-key operations can be performed anyway if the command has
only one key (e.g. "MGET foo" and "MSET foo bar" will not fail).
Do not ask me why I was using 0x (the prefix for hexadecimal notation)
when what we really need here is 0b (the prefix for binary notation).
Really, everything was working by sheer coincidence.
Since 0b has been added in PHP 5.4, we rely on plain decimal numbers
to define our constants for now.
This implementation is capable of handling "ASK" and "MOVED" replies
returned by Redis when one of the nodes asks the client for temporary
or permanent redirects of a slot to a different node.
Performances look almost on par with our client-side sharding solution
and everything looks already relatively stable.
Tests are still missing.
The reason for this change is to support the upcoming redis-cluster since
it has different behaviors compared to the client-side cluster implementation
provided by Predis. For example redis-cluster will not support key tags or
certain operations currently available with our client-side implementation.
The actual pipeline is wrapped between MULTI and EXEC to ensure that all the
commands are correctly sent and executed on the server. The whole pipeline is
discarded should it fail at a certain point during execution.
We do not use our Predis\Transaction\MultiExecContext abstraction internally
but rely on raw commands since this new executor does not really need full
support for Redis transactions.
We start using SplQueue to enqueue the commands executed inside a MULTI /
EXEC context so that we can dequeue them for parsing their replies later.
This change does not affect performances but makes the code more clean.
Using SplQueue instead of a plain PHP array to queue command instance in
the pipeline is faster and makes the underlying implementation definitely
more clean.
This change is not going to be backported to Predis v0.7 due to changes
in Predis\Pipeline\PipelineContextInterface.
Now Predis\Command\ScriptedCommand uses EVALSHA instead of EVAL internally
so that performances should be better since the client do not resend the
Lua script body on each call.
Plain EVALSHA commands are not affected and will return or throw the error.
The "throw_errors" connection parameter has been removed and replaced by the
new "exceptions" client option since exceptions on -ERR replies returned by
Redis are not generated by connection classes anymore but are thrown by the
client class and other abstractions such as pipeline contexts.
This change does not affect much people using the Predis\Client class (aside
from the different configuration) but gives much more flexibility to those
building their own pieces of code around the internal classes of Predis.
The actual code to switch to master has been implemented only in the
standard and the fire-and-forget executor classes since it does not
make sense to have it in special executors used exclusively when in
client-side clustering mode.
With a negative number Predis will count from the end of the arguments list
to calculate the actual number of keys that will be interpreted as elements
for `KEYS` by the underlying `EVAL` command.