Sfoglia il codice sorgente

Reworked HashRing::remove to handle hash collisions in a consistent way.

Daniele Alessandri 15 anni fa
parent
commit
486244be8d
1 ha cambiato i file con 16 aggiunte e 9 eliminazioni
  1. 16 9
      lib/Predis.php

+ 16 - 9
lib/Predis.php

@@ -1267,15 +1267,19 @@ namespace Predis\Utilities;
 
 class HashRing {
     const DEFAULT_REPLICAS = 128;
-    private $_ring, $_ringKeys, $_replicas;
+    private $_nodes, $_ring, $_ringKeys, $_replicas;
 
     public function __construct($replicas = self::DEFAULT_REPLICAS) {
         $this->_replicas = $replicas;
+        $this->_nodes    = array();
         $this->_ring     = array();
         $this->_ringKeys = array();
     }
 
     public function add($node) {
+        // NOTE: in case of collisions in the hashes of the nodes, the node added
+        //       last wins, thus the order in which nodes are added is significant.
+        $this->_nodes[] = $node;
         $nodeHash = (string) $node;
         $replicas = $this->_replicas;
         for ($i = 0; $i < $replicas; $i++) {
@@ -1287,14 +1291,17 @@ class HashRing {
     }
 
     public function remove($node) {
-        $nodeHash = (string) $node;
-        $replicas = $this->_replicas;
-        for ($i = 0; $i < $replicas; $i++) {
-            $key = crc32($nodeHash . ':' . $i);
-            unset($this->_ring[$key]);
-            $this->_ringKeys = array_filter($this->_ringKeys, function($rk) use($key) {
-                return $rk !== $key;
-            });
+        // NOTE: a node is removed by recreating the whole ring from scratch, in 
+        //       order to reassign possible hashes with collisions to the right node 
+        //       according to the order in which they were added in the first place.
+        $oldNodes = $this->_nodes;
+        $this->_nodes    = array();
+        $this->_ring     = array();
+        $this->_ringKeys = array();
+        foreach ($oldNodes as $oldNode) {
+            if ($oldNode !== $node) {
+                $this->add($oldNode);
+            }
         }
     }