From 6c0047c4304fc5cd84029996587d6ea1416d0578 Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Fri, 30 Sep 2011 18:41:25 +0200
Subject: [PATCH] redis-trib: better slots allocation strategy for resharding

---
 src/redis-trib.rb | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/redis-trib.rb b/src/redis-trib.rb
index 083f9740..3717f54e 100755
--- a/src/redis-trib.rb
+++ b/src/redis-trib.rb
@@ -287,10 +287,22 @@ class RedisTrib
     # instance.
     def compute_reshard_table(sources,numslots)
         moved = []
-        sources.each{|s|
+        # Sort from bigger to smaller instance, for two reasons:
+        # 1) If we take less slots than instanes it is better to start getting from
+        #    the biggest instances.
+        # 2) We take one slot more from the first instance in the case of not perfect
+        #    divisibility. Like we have 3 nodes and need to get 10 slots, we take
+        #    4 from the first, and 3 from the rest. So the biggest is always the first.
+        sources = sources.sort{|a,b| b.slots.length <=> a.slots.length}
+        sources.each_with_index{|s,i|
             # Every node will provide a number of slots proportional to the
             # slots it has assigned.
-            n = (numslots.to_f/4096*s.slots.length).ceil
+            n = (numslots.to_f/4096*s.slots.length)
+            if i == 0
+                n = n.ceil
+            else
+                n = n.floor
+            end
             s.slots.keys.sort[(0...n)].each{|slot|
                 if moved.length < numslots
                     moved << {:source => s, :slot => slot}