[MEDIUM] hash: add support for an 'avalanche' hash-type

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.
This commit is contained in:
Willy Tarreau 2010-11-24 15:04:29 +01:00
parent 4c14eaa0d4
commit 798a39cdc9
5 changed files with 28 additions and 4 deletions

View 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

View 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 */

View 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);

View 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;
}

View 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)