]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] hash: add support for an 'avalanche' hash-type
authorWilly Tarreau <w@1wt.eu>
Wed, 24 Nov 2010 14:04:29 +0000 (15:04 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 29 Nov 2010 06:28:16 +0000 (07:28 +0100)
When the number of servers is a multiple of the size of the input set,
map-based hash can be inefficient. This typically happens with 64
servers when doing URI hashing. The "avalanche" hash-type applies an
avalanche hash before performing a map lookup in order to smooth the
distribution. The result is slightly less smooth than the map for small
numbers of servers, but still better than the consistent hashing.

doc/configuration.txt
include/types/backend.h
src/backend.c
src/cfgparse.c
src/lb_chash.c

index a15b03591e47314d64c567b99f6944c4c7ba1ab1..7794e19321c1444a9d381a031b2e3f038b5364c1 100644 (file)
@@ -2235,6 +2235,15 @@ hash-type <method>
                 to a farm, most connections will be redistributed to different
                 servers. This can be inconvenient with caches for instance.
 
+    avalanche   this mechanism uses the default map-based hashing described
+                above but applies a full avalanche hash before performing the
+                mapping. The result is a slightly less smooth hash for most
+                situations, but the hash becomes better than pure map-based
+                hashes when the number of servers is a multiple of the size of
+                the input set. When using URI hash with a number of servers
+                multiple of 64, it's desirable to change the hash type to
+                this value.
+
     consistent  the hash table is a tree filled with many occurrences of each
                 server. The hash key is looked up in the tree and the closest
                 server is chosen. This hash is dynamic, it supports changing
index 91d95b18134a72044a2d343f0021ad1b537cc0a9..a3237ffb70c3d09cbc6755e666a628b5a0670a26 100644 (file)
@@ -94,7 +94,8 @@
 /* hash types */
 #define BE_LB_HASH_MAP    0x000000 /* map-based hash (default) */
 #define BE_LB_HASH_CONS   0x100000 /* consistent hashbit to indicate a dynamic algorithm */
-#define BE_LB_HASH_TYPE   0x100000 /* get/clear hash types */
+#define BE_LB_HASH_AVAL   0x200000 /* run an avalanche hash before a map */
+#define BE_LB_HASH_TYPE   0x300000 /* get/clear hash types */
 
 /* various constants */
 
index 26bc8828dbf73e401597c966eaa9685b0794002e..ff06d2c2768a6394afc261e864bb1e7363958806 100644 (file)
@@ -118,6 +118,8 @@ struct server *get_server_sh(struct proxy *px, const char *addr, int len)
                h ^= ntohl(*(unsigned int *)(&addr[l]));
                l += sizeof (int);
        }
+       if ((px->lbprm.algo & BE_LB_HASH_TYPE) != BE_LB_HASH_MAP)
+               h = full_hash(h);
  hash_done:
        if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
                return chash_get_server_hash(px, h);
@@ -165,6 +167,8 @@ struct server *get_server_uh(struct proxy *px, char *uri, int uri_len)
 
                hash = c + (hash << 6) + (hash << 16) - hash;
        }
+       if ((px->lbprm.algo & BE_LB_HASH_TYPE) != BE_LB_HASH_MAP)
+               hash = full_hash(hash);
  hash_done:
        if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
                return chash_get_server_hash(px, hash);
@@ -217,6 +221,8 @@ struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
                                        uri_len--;
                                        p++;
                                }
+                               if ((px->lbprm.algo & BE_LB_HASH_TYPE) != BE_LB_HASH_MAP)
+                                       hash = full_hash(hash);
                                if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
                                        return chash_get_server_hash(px, hash);
                                else
@@ -285,6 +291,8 @@ struct server *get_server_ph_post(struct session *s)
                                        p++;
                                        /* should we break if vlen exceeds limit? */
                                }
+                               if ((px->lbprm.algo & BE_LB_HASH_TYPE) != BE_LB_HASH_MAP)
+                                       hash = full_hash(hash);
                                if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
                                        return chash_get_server_hash(px, hash);
                                else
@@ -374,6 +382,8 @@ struct server *get_server_hh(struct session *s)
                        p--;
                }
        }
+       if ((px->lbprm.algo & BE_LB_HASH_TYPE) != BE_LB_HASH_MAP)
+               hash = full_hash(hash);
  hash_done:
        if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
                return chash_get_server_hash(px, hash);
@@ -419,6 +429,8 @@ struct server *get_server_rch(struct session *s)
                len--;
                p++;
        }
+       if ((px->lbprm.algo & BE_LB_HASH_TYPE) != BE_LB_HASH_MAP)
+               hash = full_hash(hash);
  hash_done:
        if (px->lbprm.algo & BE_LB_LKUP_CHTREE)
                return chash_get_server_hash(px, hash);
index d3223ff6df89bab38df3745a00237e3e18b7de39..124e599b3ea7285e72a3542933317851089c2e3d 100644 (file)
@@ -3788,8 +3788,12 @@ stats_error_parsing:
                        curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
                        curproxy->lbprm.algo |= BE_LB_HASH_MAP;
                }
+               else if (strcmp(args[1], "avalanche") == 0) {   /* use full hash before map-based hashing */
+                       curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
+                       curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
+               }
                else {
-                       Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
+                       Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
index a2582f0680d2dd9eeeaa03183ef1d7f8062dae87..58f1c9eaae8b15e984b9a5a341b2bdb11d8656f1 100644 (file)
@@ -271,8 +271,6 @@ struct server *chash_get_server_hash(struct proxy *p, unsigned int hash)
        else
                return NULL;
 
-       hash = full_hash(hash);
-
        /* find the node after and the node before */
        next = eb32_lookup_ge(root, hash);
        if (!next)