소스 검색

Improve handling of slots mapping via parameters.

When using redis-cluster it is now also possible to pass one slot or
non-contiguous ranges of slots via connection parameters in order to
improve the ability to pre-configure the slots map on the client.

Here is an example:

  $parameters = [
    'tcp://10.0.0.1:6379?slots=0-5460,5500-5600,11000',
    'tcp://10.0.0.2:6379?slots=5461-5499,5600-10921',
    'tcp://10.0.0.3:6379?slots=10922-10999,11001-16383',
  ];

This commit fixes #312 (props to @kenotr0n for the original PR).
Daniele Alessandri 9 년 전
부모
커밋
354e5e26da
2개의 변경된 파일48개의 추가작업 그리고 4개의 파일을 삭제
  1. 11 2
      src/Connection/Aggregate/RedisCluster.php
  2. 37 2
      tests/Predis/Connection/Aggregate/RedisClusterTest.php

+ 11 - 2
src/Connection/Aggregate/RedisCluster.php

@@ -164,8 +164,15 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
                 continue;
             }
 
-            $slots = explode('-', $parameters->slots, 2);
-            $this->setSlots($slots[0], $slots[1], $connectionID);
+            foreach (explode(',', $parameters->slots) as $slotRange) {
+                $slots = explode('-', $slotRange, 2);
+
+                if (!isset($slots[1])) {
+                    $slots[1] = $slots[0];
+                }
+
+                $this->setSlots($slots[0], $slots[1], $connectionID);
+            }
         }
     }
 
@@ -205,6 +212,8 @@ class RedisCluster implements ClusterInterface, \IteratorAggregate, \Countable
     /**
      * Returns the current slots map for the cluster.
      *
+     * The order of the returned $slot => $server dictionary is not guaranteed.
+     *
      * @return array
      */
     public function getSlotsMap()

+ 37 - 2
tests/Predis/Connection/Aggregate/RedisClusterTest.php

@@ -333,7 +333,7 @@ class RedisClusterTest extends PredisTestCase
     /**
      * @group disconnected
      */
-    public function testCanAssignConnectionsToCustomSlotsFromParameters()
+    public function testCanAssignConnectionsToRangeOfSlotsFromParameters()
     {
         $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379?slots=0-5460');
         $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380?slots=5461-10921');
@@ -344,15 +344,50 @@ class RedisClusterTest extends PredisTestCase
         $cluster->add($connection2);
         $cluster->add($connection3);
 
+        $cluster->buildSlotsMap();
+
         $expectedMap = array_merge(
             array_fill(0, 5461, '127.0.0.1:6379'),
             array_fill(5460, 5461, '127.0.0.1:6380'),
             array_fill(10921, 5462, '127.0.0.1:6381')
         );
 
+        $actualMap = $cluster->getSlotsMap();
+        ksort($actualMap);
+
+        $this->assertSame($expectedMap, $actualMap);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testCanAssignConnectionsToSingleSlotOrRangesOfSlotsFromParameters()
+    {
+        $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379?slots=0-5460,5500-5600,11000');
+        $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380?slots=5461-5499,5600-10921');
+        $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381?slots=10922-10999,11001-16383');
+
+        $cluster = new RedisCluster(new Connection\Factory());
+        $cluster->add($connection1);
+        $cluster->add($connection2);
+        $cluster->add($connection3);
+
         $cluster->buildSlotsMap();
 
-        $this->assertSame($expectedMap, $cluster->getSlotsMap());
+        $expectedMap = array_merge(
+            array_fill(0, 5461, '127.0.0.1:6379'),
+            array_fill(5460, 39, '127.0.0.1:6380'),
+            array_fill(5499, 101, '127.0.0.1:6379'),
+            array_fill(5599, 5321, '127.0.0.1:6380'),
+            array_fill(10921, 78, '127.0.0.1:6381'),
+            array_fill(11000, 1, '127.0.0.1:6379'),
+            array_fill(11000, 5383, '127.0.0.1:6381')
+        );
+
+        $actualMap = $cluster->getSlotsMap();
+        ksort($actualMap);
+
+        $this->assertSame($expectedMap, $actualMap);
     }
 
     /**