Created
August 13, 2012 15:12
-
-
Save funny-falcon/3341656 to your computer and use it in GitHub Desktop.
Consistent hash from Google Guava Core libraries
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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