فهرست منبع

Fetch updated slots map from node indicated by -MOVED response.

This optimization makes it possible to fetch the slots map directly
from the server indicated by the -MOVED response eliminating the need
to use a random node in the pool, which in turn could require Predis
to open a new and useless connection.
Daniele Alessandri 11 سال پیش
والد
کامیت
43a6ae181e
3فایلهای تغییر یافته به همراه53 افزوده شده و 5 حذف شده
  1. 5 0
      CHANGELOG.md
  2. 7 5
      lib/Predis/Connection/RedisCluster.php
  3. 41 0
      tests/Predis/Connection/RedisClusterTest.php

+ 5 - 0
CHANGELOG.md

@@ -10,6 +10,11 @@ v0.8.7 (2014-xx-xx)
   to fetch the updated slots map from redis-cluster. This change requires users
   to upgrade Redis nodes to >= 3.0.0b7.
 
+- The updated slots map is now fetched automatically from redis-cluster upon the
+  first `-MOVED` response by default. This change makes it possible to feed the
+  client constructor with only a few nodes of the actual cluster composition,
+  without needing a more complex configuration.
+
 - Implemented support for `PING` in PUB/SUB loop for Redis >= 3.0.0b8.
 
 - The default client-side sharding strategy and the one for redis-cluster now

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

@@ -169,14 +169,16 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
     }
 
     /**
-     * Generates the current slots map by fetching the cluster configuration to
-     * one of the nodes by leveraging the CLUSTER SLOTS command.
+     * Generates an updated slots map fetching the cluster configuration using
+     * the CLUSTER NODES command against the specified node or a random one from
+     * the pool.
      *
+     * @param  SingleConnectionInterface $connection Optional connection instance.
      * @return array
      */
-    public function askClusterNodes()
+    public function askClusterNodes(SingleConnectionInterface $connection = null)
     {
-        if (!$connection = $this->getRandomConnection()) {
+        if (!$connection && !$connection = $this->getRandomConnection()) {
             return array();
         }
 
@@ -402,7 +404,7 @@ class RedisCluster implements ClusterConnectionInterface, IteratorAggregate, Cou
         }
 
         if ($this->askClusterNodes) {
-            $this->askClusterNodes();
+            $this->askClusterNodes($connection);
         }
 
         $this->move($connection, $slot);

+ 41 - 0
tests/Predis/Connection/RedisClusterTest.php

@@ -649,6 +649,47 @@ class RedisClusterTest extends PredisTestCase
         $this->assertSame($cluster->getConnectionBySlot('6144'), $connection1);
     }
 
+    /**
+     * @group disconnected
+     */
+    public function testAskSlotsMapToRedisClusterOnMovedResponseByDefault()
+    {
+        $cmdGET = RawCommand::create('GET', 'node:1001');
+        $rspMOVED = new ResponseError('MOVED 1970 127.0.0.1:6380');
+        $rspSlotsArray = array(
+            array(0   ,  8191, array('127.0.0.1', 6379)),
+            array(8192, 16383, array('127.0.0.1', 6380)),
+        );
+
+        $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
+        $connection1->expects($this->once())
+                    ->method('executeCommand')
+                    ->with($cmdGET)
+                    ->will($this->returnValue($rspMOVED));
+
+        $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
+        $connection2->expects($this->at(0))
+                    ->method('executeCommand')
+                    ->with($this->isRedisCommand('CLUSTER', array('SLOTS')))
+                    ->will($this->returnValue($rspSlotsArray));
+        $connection2->expects($this->at(2))
+                    ->method('executeCommand')
+                    ->with($cmdGET)
+                    ->will($this->returnValue('foobar'));
+
+        $factory = $this->getMock('Predis\Connection\ConnectionFactory');
+        $factory->expects($this->once())
+                ->method('create')
+                ->with(array('host' => '127.0.0.1', 'port' => '6380'))
+                ->will($this->returnValue($connection2));
+
+        $cluster = new RedisCluster($factory);
+        $cluster->add($connection1);
+
+        $this->assertSame('foobar', $cluster->executeCommand($cmdGET));
+        $this->assertSame(2, count($cluster));
+    }
+
     /**
      * @group disconnected
      * @expectedException Predis\NotSupportedException