Skip to content

PrabinKuSabat/FlipHash-main

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”€ FlipHash β€” Constant-Time Consistent Range-Hashing

A Java & C implementation of the FlipHash algorithm from the research paper by Charles Masson & Homin K. Lee.

Paper Language Java Language C Author


πŸ“œ Research Paper

Title: FlipHash: A Constant-Time Consistent Range-Hashing Algorithm
Authors: Charles Masson, Homin K. Lee
Published: arXiv:2402.17549 [cs.DS] β€” February 27, 2024
DOI: 10.48550/arXiv.2402.17549
Full Paper: arxiv.org/abs/2402.17549


🎯 What is FlipHash?

Consistent range-hashing is a foundational technique in distributed systems. It assigns keys (requests, data chunks, user IDs) to one of N numbered resources (servers, cache nodes, shards) such that:

  1. Keys are evenly distributed across all N resources
  2. When N changes (a server is added or removed), only the minimum required keys are remapped β€” no unnecessary reshuffling occurs

FlipHash solves this with O(1) constant-time complexity β€” beating the widely-used Jump Consistent Hash which runs in O(log N).

Real-World Use Cases

  • Load balancers routing HTTP requests to backend servers
  • Distributed caches (like Memcached clusters) assigning keys to nodes
  • Sharded databases mapping records to shards
  • Content delivery networks routing assets to edge servers

🧠 The Algorithm Explained

FlipHash is composed of two functions: fliphashPow2 for power-of-2 resource counts and fliphashGeneral for any arbitrary N.

πŸ”‘ Seeding

All hash calls use a two-dimensional seed:

seed(a, b) = a + (b << 16)

This lets the algorithm derive multiple independent hash values for the same key without storing state, simply by varying a and b.


Step 1 β€” fliphashPow2(key, r) β†’ bucket in [0, 2Κ³)

Maps a key to range [0, 2^r) consistently:

1.  a  =  H(key, seed(0, 0))  mod  2^r
             ↓
2.  b  =  ⌊logβ‚‚(a)βŒ‹                   ← position of highest set bit in a
             ↓
3.  c  =  H(key, seed(b, 0))  mod  2^b
             ↓
4.  return  a + c

Intuition: a falls in the range [2^b, 2^(b+1)). Adding c ∈ [0, 2^b) fills in all buckets in [2^b, 2^(b+1) + 2^b) uniformly. The second hash ensures that when N shrinks or grows, keys are remapped predictably.

Java code from FlipHash.java:

private static long fliphashPow2(String key, int twoPower) {
    Hasher64 xxh3 = XXH3_64.create(seeding((short) 0, (short) 0));
    long a = xxh3.hashCharsToLong(key) & ((1L << twoPower) - 1);  // a mod 2^r

    long temp = a; int b = 0;
    while (temp > 1) { temp >>= 1; b++; }    // b = floor(logβ‚‚(a))

    xxh3 = XXH3_64.create(seeding((short) b, (short) 0));
    long c = xxh3.hashCharsToLong(key) & ((1L << b) - 1);         // c mod 2^b
    return a + c;
}

Step 2 β€” fliphashGeneral(key, N) β†’ bucket in [0, N)

Handles any arbitrary N using fliphashPow2 as a building block:

1.  r  =  ceil(logβ‚‚(N))                    ← smallest r with 2^r β‰₯ N
            ↓
2.  d  =  fliphashPow2(key, r)
            ↓
3.  d < N?  β†’  return d                   ← direct hit βœ…
            ↓
4.  d β‰₯ N (forbidden zone [N, 2^r)):
    For i = 0 β†’ 63:
        e = H(key, seed(r-1, i)) mod 2^r

        e < 2^(r-1)  β†’  return fliphashPow2(key, r-1)    ← "flip down" πŸ”ƒ
        e < N        β†’  return e                           ← remap to valid zone βœ…
            ↓
5.  Fallback: return fliphashPow2(key, r-1)

The "flip" insight: When a key lands in the forbidden zone [N, 2^r), the algorithm flips it either down to [0, 2^(r-1)) or maps it directly to the valid upper zone [2^(r-1), N). This is the namesake operation that gives FlipHash its O(1) complexity β€” no iteration over the full N range.

Java code from FlipHash.java:

public static long fliphashGeneral(String key, Resource resource) {
    long N = resource.count;
    int r = 0;
    for (long temp = N; temp > 0; temp >>= 1) { r++; }  // r = ⌈logβ‚‚(N)βŒ‰

    long d = fliphashPow2(key, r);
    if (d < N) return d;                   // direct hit

    long halfRange = 1L << (r - 1);        // 2^(r-1)
    for (int i = 0; i < 64; i++) {
        Hasher64 xxh3 = XXH3_64.create(seeding((short)(r-1), (short)i));
        long e = xxh3.hashCharsToLong(key) & ((1L << r) - 1);

        if (e < halfRange) return fliphashPow2(key, r - 1);  // flip down
        if (e < N)         return e;                          // remap
    }
    return fliphashPow2(key, r - 1);  // fallback
}

πŸ† FlipHash vs Jump Consistent Hash

Property Jump Consistent Hash FlipHash
Time Complexity O(log N) O(1)
Memory O(1) O(1)
Even distribution βœ… βœ…
Minimal remapping on change βœ… βœ…
Sequential resource indexing Required Required
Speed at large N Slower Faster

From the paper: "FlipHash beats Jump Consistent Hash's cost both theoretically and in experiments over practical settings."


πŸ“ Project Structure

FlipHash-main/
β”œβ”€β”€ Java implementation/     # Full Java implementation with load balancer simulation
β”‚   └── fliphash/            # Core package: FlipHash algorithm + server/client demo
β”œβ”€β”€ C implementation./       # C implementation of the FlipHash algorithm
β”œβ”€β”€ Final Submission/        # Final academic project submission package
β”œβ”€β”€ Jar files/               # Precompiled standalone JAR files
β”œβ”€β”€ Client.java              # Standalone client entrypoint
└── README.md                # This file

πŸš€ Quick Start

Java

cd "Java implementation/fliphash"

# Compile
javac -cp ".:jna-5.13.0.jar:oshi-core-6.3.0.jar:slf4j-api-2.0.9.jar:slf4j-simple-2.0.9.jar" *.java

# Run the core algorithm
java -cp ".:jna-5.13.0.jar:oshi-core-6.3.0.jar:slf4j-api-2.0.9.jar:slf4j-simple-2.0.9.jar" fliphash.FlipHash

On Windows replace : with ; in the classpath.

C

cd "C implementation."
make
./onlyfliphash

πŸ™ Credits & Acknowledgements

πŸ“š FlipHash Algorithm

Authors: Charles Masson & Homin K. Lee
Paper: FlipHash: A Constant-Time Consistent Range-Hashing Algorithm
arXiv: arXiv:2402.17549 [cs.DS]
This implementation is based directly on the algorithm described in this paper.

⚑ XXH3 Hashing

Author: Yann Collet
Repository: github.com/Cyan4973/xxHash
The XXH3-64 hash function is used as the underlying hash primitive in all FlipHash operations.

πŸ’» OSHI β€” Operating System & Hardware Information

Repository: github.com/oshi/oshi
Used for real-time CPU and memory monitoring in the load balancer demonstration.

πŸ”— JNA β€” Java Native Access

Repository: github.com/java-native-access/jna
Enables the Java implementation to interface with native system libraries.


Implemented by Prabin Kumar Sabat
Based on research by Charles Masson & Homin K. Lee


πŸ“¬ Connect with me

Email Β  LinkedIn Β  Instagram



Sri Sathya Sai Institute of Higher Learning
Sri Sathya Sai Institute of Higher Learning

Prasanthi Nilayam (Puttaparthi) β€” Department of Mathematics and Computer Science

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages