Make it possible to pre-associate slots to a connection.

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 commit is contained in:
Daniele Alessandri
2012-07-29 14:14:11 +02:00
parent 2ba54a0e1c
commit 8559c2cb30
+29 -1
View File
@@ -29,6 +29,7 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
{
private $pool;
private $slots;
private $slotsMap;
private $connections;
private $distributor;
private $cmdHasher;
@@ -40,6 +41,7 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
{
$this->pool = array();
$this->slots = array();
$this->slotsMap = array();
$this->connections = $connections ?: new ConnectionFactory();
$this->distributor = new CRC16HashGenerator();
$this->cmdHasher = new RedisClusterHashStrategy();
@@ -119,6 +121,27 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
return false;
}
/**
* Preassociate a connection to a set of slots to avoid runtime guessing.
*
* @todo Check type or existence of the specified connection.
*
* @param int $first Initial slot.
* @param int $last Last slot.
* @param ConnectionSingleInterface|string $connection ID or connection instance.
*/
public function setSlots($first, $last, $connection)
{
$connection = (string) $connection;
if ($first < 0 || $first > 4095 || $last < 0 || $last > 4095 || $last < $first) {
throw new \OutOfBoundsException("Invalid slot values for $connection: [$first-$last]");
}
$slots = array_fill($first, $last - $first + 1, $connection);
$this->slotsMap = array_merge($this->slotsMap, $slots);
}
/**
* {@inheritdoc}
*/
@@ -142,7 +165,12 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
return $this->slots[$slot];
}
$this->slots[$slot] = $connection = $this->pool[array_rand($this->pool)];
if (isset($this->slotsMap[$slot])) {
$this->slots[$slot] = $connection = $this->pool[$this->slotsMap[$slot]];
}
$connection = $this->pool[isset($this->slotsMap[$slot]) ? $this->slotsMap[$slot] : array_rand($this->pool)];
$this->slots[$slot] = $connection;
return $connection;
}