Skip to content

Instantly share code, notes, and snippets.

@funny-falcon
Created August 13, 2012 15:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save funny-falcon/3341656 to your computer and use it in GitHub Desktop.
Save funny-falcon/3341656 to your computer and use it in GitHub Desktop.
Consistent hash from Google Guava Core libraries
/**
* Assigns to {@code input} a "bucket" in the range {@code [0, buckets)}, in a uniform
* manner that minimizes the need for remapping as {@code buckets} grows. That is,
* {@code consistentHash(h, n)} equals:
*
* <ul>
* <li>{@code n - 1}, with approximate probability {@code 1/n}
* <li>{@code consistentHash(h, n - 1)}, otherwise (probability {@code 1 - 1/n})
* </ul>
*
* <p>See the <a href="http://en.wikipedia.org/wiki/Consistent_hashing">wikipedia
* article on consistent hashing</a> for more information.
*/
public static int consistentHash(long input, int buckets) {
checkArgument(buckets > 0, "buckets must be positive: %s", buckets);
long h = input;
int candidate = 0;
int next;
// Jump from bucket to bucket until we go out of range
while (true) {
// See http://en.wikipedia.org/wiki/Linear_congruential_generator
// These values for a and m come from the C++ version of this function.
h = 2862933555777941757L * h + 1;
double inv = 0x1.0p31 / ((int) (h >>> 33) + 1);
next = (int) ((candidate + 1) * inv);
if (next >= 0 && next < buckets) {
candidate = next;
} else {
return candidate;
}
}
}
K = 2862933555777941757
M64 = 2**64-1
L = (2**31).to_f
def conshash(h, buckets)
candidate = 0
while true
h = (h*K + 1) & M64
inv = L / ((h >> 33) + 1)
nxt = ((candidate + 1) * inv).to_i
break if nxt >= buckets || nxt < 0
candidate = nxt
end
candidate
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment