You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by br...@apache.org on 2010/10/13 20:14:54 UTC

svn commit: r1022221 - in /cassandra/trunk: conf/cassandra.yaml src/java/org/apache/cassandra/config/Config.java src/java/org/apache/cassandra/config/DatabaseDescriptor.java src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java

Author: brandonwilliams
Date: Wed Oct 13 18:14:52 2010
New Revision: 1022221

URL: http://svn.apache.org/viewvc?rev=1022221&view=rev
Log:
Add badness threshold to the dynamic snitch for replica 'pinning'. Patch by brandonwilliams, reviewed by jbellis for CASSANDRA-1519

Modified:
    cassandra/trunk/conf/cassandra.yaml
    cassandra/trunk/src/java/org/apache/cassandra/config/Config.java
    cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
    cassandra/trunk/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java

Modified: cassandra/trunk/conf/cassandra.yaml
URL: http://svn.apache.org/viewvc/cassandra/trunk/conf/cassandra.yaml?rev=1022221&r1=1022220&r2=1022221&view=diff
==============================================================================
--- cassandra/trunk/conf/cassandra.yaml (original)
+++ cassandra/trunk/conf/cassandra.yaml Wed Oct 13 18:14:52 2010
@@ -220,6 +220,18 @@ endpoint_snitch: org.apache.cassandra.lo
 # and avoid reading from hosts that have slowed (due to compaction,
 # for instance)
 dynamic_snitch: true
+# controls how often to perform the more expensive part of host score
+# calculation
+dynamic_snitch_update_interval_in_ms: 100 
+# controls how often to reset all host scores, allowing a bad host to
+# possibly recover
+dynamic_snitch_reset_interval_in_ms: 600000
+# if set greater than zero and read_repair_chance is < 1.0, this will allow
+# 'pinning' of replicas to hosts in order to increase cache capacity.
+# The badness threshold will control how much worse the pinned host has to be
+# before the dynamic snitch will prefer other replicas over it.  This is
+# expressed as a double which represents a percentage.
+dynamic_snitch_badness_threshold: 0.0
 
 # request_scheduler -- Set this to a class that implements
 # RequestScheduler, which will schedule incoming client requests

Modified: cassandra/trunk/src/java/org/apache/cassandra/config/Config.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/config/Config.java?rev=1022221&r1=1022220&r2=1022221&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/config/Config.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/config/Config.java Wed Oct 13 18:14:52 2010
@@ -97,7 +97,10 @@ public class Config
     
     public String endpoint_snitch;
     public Boolean dynamic_snitch = false;
-    
+    public Integer dynamic_snitch_update_interval_in_ms = 100;
+    public Integer dynamic_snitch_reset_interval_in_ms = 600000;
+    public Double dynamic_snitch_badness_threshold = 0.0;
+
     public String request_scheduler;
     public RequestSchedulerId request_scheduler_id;
     public RequestSchedulerOptions request_scheduler_options;

Modified: cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java?rev=1022221&r1=1022220&r2=1022221&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/config/DatabaseDescriptor.java Wed Oct 13 18:14:52 2010
@@ -561,6 +561,11 @@ public class    DatabaseDescriptor
                     throw new ConfigurationException("read_repair_chance must be between 0.0 and 1.0 (0% and 100%)");
                 }
 
+                if (conf.dynamic_snitch_badness_threshold < 0.0 || conf.dynamic_snitch_badness_threshold > 1.0)
+                {
+                    throw new ConfigurationException("dynamic_snitch_badness_threshold must be between 0.0 and 1.0 (0% and 100%)");
+                }
+                
                 if (cf.min_compaction_threshold < 0 || cf.max_compaction_threshold < 0)
                 {
                     throw new ConfigurationException("min/max_compaction_thresholds must be non-negative integers.");
@@ -1106,4 +1111,19 @@ public class    DatabaseDescriptor
     {
         return new File(conf.saved_caches_directory + File.separator + ksName + "-" + cfName + "-KeyCache");
     }
+
+    public static int getDynamicUpdateInterval()
+    {
+        return conf.dynamic_snitch_update_interval_in_ms;
+    }
+
+    public static int getDynamicResetInterval()
+    {
+        return conf.dynamic_snitch_reset_interval_in_ms;
+    }
+
+    public static double getDynamicBadnessThreshold()
+    {
+        return conf.dynamic_snitch_badness_threshold;
+    }
 }

Modified: cassandra/trunk/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java?rev=1022221&r1=1022220&r2=1022221&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java Wed Oct 13 18:14:52 2010
@@ -34,6 +34,7 @@ import org.apache.cassandra.net.Messagin
 import org.apache.cassandra.service.StorageService;
 import org.apache.cassandra.utils.AbstractStatsDeque;
 import org.apache.cassandra.utils.FBUtilities;
+import org.apache.cassandra.config.DatabaseDescriptor;
 
 /**
  * A dynamic snitch that sorts endpoints by latency with an adapted phi failure detector
@@ -41,8 +42,9 @@ import org.apache.cassandra.utils.FBUtil
 public class DynamicEndpointSnitch extends AbstractEndpointSnitch implements ILatencySubscriber, DynamicEndpointSnitchMBean
 {
     private static int UPDATES_PER_INTERVAL = 10000;
-    private static int UPDATE_INTERVAL_IN_MS = 100;
-    private static int RESET_INTERVAL_IN_MS = 60000 * 10;
+    private static int UPDATE_INTERVAL_IN_MS = DatabaseDescriptor.getDynamicUpdateInterval();
+    private static int RESET_INTERVAL_IN_MS = DatabaseDescriptor.getDynamicResetInterval();
+    private static double BADNESS_THRESHOLD = DatabaseDescriptor.getDynamicBadnessThreshold();
     private static int WINDOW_SIZE = 100;
     private boolean registered = false;
 
@@ -119,6 +121,18 @@ public class DynamicEndpointSnitch exten
     public List<InetAddress> sortByProximity(final InetAddress address, List<InetAddress> addresses)
     {
         assert address.equals(FBUtilities.getLocalAddress()); // we only know about ourself
+        if (BADNESS_THRESHOLD == 0)
+        {
+            return sortByProximityWithScore(address, addresses);
+        }
+        else
+        {
+            return sortByProximityWithBadness(address, addresses);
+        }
+    }
+
+    private List<InetAddress> sortByProximityWithScore(final InetAddress address, List<InetAddress> addresses)
+    {
         Collections.sort(addresses, new Comparator<InetAddress>()
         {
             public int compare(InetAddress a1, InetAddress a2)
@@ -129,6 +143,25 @@ public class DynamicEndpointSnitch exten
         return addresses;
     }
 
+    private List<InetAddress> sortByProximityWithBadness(final InetAddress address, List<InetAddress> addresses)
+    {
+        if (addresses.size() < 2)
+            return addresses;
+        List<InetAddress> snitchordered = subsnitch.sortByProximity(address, addresses);
+        Double first = scores.get(snitchordered.get(0));
+        if (first == null)
+            return snitchordered;
+        for (InetAddress addr : addresses)
+        {
+            Double next = scores.get(addr);
+            if (next == null)
+                return snitchordered;
+            if ((first - next) / first > BADNESS_THRESHOLD)
+                return sortByProximityWithScore(address, addresses);
+        }
+        return snitchordered;
+    }
+
     public int compareEndpoints(InetAddress target, InetAddress a1, InetAddress a2)
     {
         Double scored1 = scores.get(a1);