Browse Source

Pre-associate connections to slot ranges using connection parameters.

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.
Daniele Alessandri 13 years ago
parent
commit
febd99421f
1 changed files with 22 additions and 7 deletions
  1. 22 7
      lib/Predis/Connection/RedisCluster.php

+ 22 - 7
lib/Predis/Connection/RedisCluster.php

@@ -87,7 +87,12 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
     public function add(SingleConnectionInterface $connection)
     {
         $parameters = $connection->getParameters();
-        $this->pool["{$parameters->host}:{$parameters->port}"] = $connection;
+        $this->pool[$connectionID = "{$parameters->host}:{$parameters->port}"] = $connection;
+
+        if (isset($parameters->slots)) {
+            @list($first, $last) = explode('-', $parameters->slots, 2);
+            $this->setSlots($first, $last, $connectionID);
+        }
     }
 
     /**
@@ -128,17 +133,15 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
      *
      * @param int $first Initial slot.
      * @param int $last Last slot.
-     * @param ConnectionSingleInterface|string $connection ID or connection instance.
+     * @param SingleConnectionInterface|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);
+        $slots = array_fill($first, $last - $first + 1, (string) $connection);
         $this->slotsMap = array_merge($this->slotsMap, $slots);
     }
 
@@ -209,8 +212,7 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
 
         switch ($request) {
             case 'MOVED':
-                $this->add($connection);
-                $this->slots[(int) $slot] = $connection;
+                $this->move($connection, $slot);
                 return $this->executeCommand($command);
 
             case 'ASK':
@@ -221,6 +223,19 @@ class RedisCluster implements ClusterConnectionInterface, \IteratorAggregate, \C
         }
     }
 
+    /**
+     * Assign the connection instance to a new slot and adds it to the
+     * pool if the connection was not already part of the pool.
+     *
+     * @param SingleConnectionInterface $connection Connection instance
+     * @param int $slot Target slot.
+     */
+    protected function move(SingleConnectionInterface $connection, $slot)
+    {
+        $this->pool[(string) $connection] = $connection;
+        $this->slots[(int) $slot] = $connection;
+    }
+
     /**
      * Returns the underlying command hash strategy used to hash
      * commands by their keys.