Rendezvous or highest random weight (HRW) hashing is an algorithm that allows clients to achieve distributed agreement on a set of options out of a possible set of options. A typical application is when clients need to agree on which sites (or proxies) objects are assigned to.

Consistent hashing addresses the special case using a different method. Rendezvous hashing is both much simpler and more general than consistent hashing (see below).

History

Rendezvous hashing was invented by David Thaler and Chinya Ravishankar at the University of Michigan in 1996. Consistent hashing appeared a year later in the literature.

Given its simplicity and generality, rendezvous hashing is now being preferred to consistent hashing in real-world applications. Rendezvous hashing was used very early on in many applications including mobile caching, router design, secure key establishment, and sharding and distributed databases. Other examples of real-world systems that use Rendezvous Hashing include the GitHub load balancer, the Apache Ignite distributed database, the Tahoe-LAFS file store, the CoBlitz large-file distribution service, Apache Druid, IBM's Cloud Object Store, the Arvados Data Management System, Apache Kafka, and the Twitter EventBus pub/sub platform.

One of the first applications of rendezvous hashing was to enable multicast clients on the Internet (in contexts such as the MBONE) to identify multicast rendezvous points in a distributed fashion. It was used in 1998 by Microsoft's Cache Array Routing Protocol (CARP) for distributed cache coordination and routing. Some Protocol Independent Multicast routing protocols use rendezvous hashing to pick a rendezvous point.

Problem definition and approach Algorithm Rendezvous hashing solves a general version of the distributed hash table problem: We are given a set of sites (servers or proxies, say). How can any set of clients, given an object , agree on a k-subset of sites to assign to ? The standard version of the problem uses k = 1. Each client is to make its selection independently, but all clients must end up picking the same subset of sites. This is non-trivial if we add a minimal disruption constraint, and require that when a site fails or is removed, only objects mapping to that site need be reassigned to other sites.

The basic idea is to give each site a score (a weight) for each object , and assign the object to the highest scoring site. All clients first agree on a hash function . For object , the site is defined to have weight . Each client independently computes these weights and picks the k sites that yield the k largest hash values. The clients have thereby achieved distributed -agreement.

If a site is added or removed, only the objects mapping to are remapped to different sites, satisfying the minimal disruption constraint above. The HRW assignment can be computed independently by any client, since it depends only on the identifiers for the set of sites and the object being assigned.

HRW easily accommodates different capacities among sites. If site has twice the capacity of the other sites, we simply represent twice in the list, say, as . Clearly, twice as many objects will now map to as to the other sites.

Properties

Consider the simple version of the problem, with k = 1, where all clients are to agree on a single site for an object O. Approaching the problem naively, it might appear sufficient to treat the n sites as buckets in a hash table and hash the object name O into this table. Unfortunately, if any of the sites fails or is unreachable, the hash table size changes, forcing all objects to be remapped. This massive disruption makes such direct hashing unworkable.

Under rendezvous hashing, however, clients handle site failures by picking the site that yields the next largest weight. Remapping is required only for objects currently mapped to the failed site, and disruption is minimal.

Rendezvous hashing has the following properties:

Low overhead: The hash function used is efficient, so overhead at the clients is very low. Load balancing: Since the hash function is randomizing, each of the n sites is equally likely to receive the object O. Loads are uniform across the sites. Site capacity: Sites with different capacities can be represented in the site list with multiplicity in proportion to capacity. A site with twice the capacity of the other sites will be represented twice in the list, while every other site is represented once. High hit rate: Since all clients agree on placing an object O into the same site SO, each fetch or placement of O into SO yields the maximum utility in terms of hit rate. The object O will always be found unless it is evicted by some replacement algorithm at SO. Minimal disruption: When a site fails, only the objects mapped to that site need to be remapped. Disruption is at the minimal possible level. Distributed k-agreement: Clients can reach distributed agreement on k sites simply by selecting the top k sites in the ordering.

O(log n) running time via skeleton-based hierarchical rendezvous hashing The standard version of Rendezvous Hashing described above works quite well for moderate n, but when is extremely large, the hierarchical use of Rendezvous Hashing achieves running time. This approach creates a virtual hierarchical structure (called a "skeleton"), and achieves running time by applying HRW at each level while descending the hierarchy. The idea is to first choose some constant and organize the sites into clusters Next, build a virtual hierarchy by choosing a constant and imagining these clusters placed at the leaves of a tree of virtual nodes, each with fanout .

In the accompanying diagram, the cluster size is , and the skeleton fanout is . Assuming 108 sites (real nodes) for convenience, we get a three-tier virtual hierarchy. Since , each virtual node has a natural numbering in octal. Thus, the 27 virtual nodes at the lowest tier would be numbered in octal (we can, of course, vary the fanout at each level - in that case, each node will be identified with the corresponding mixed-radix number).

The easiest way to understand the virtual hierarchy is by starting at the top, and descending the virtual hierarchy. We successively apply Rendezvous Hashing to the set of virtual nodes at each level of the hierarchy, and descend the branch defined by the winning virtual node. We can in fact start at any level in the virtual hierarchy. Starting lower in the hierarchy requires more hashes, but may improve load distribution in the case of failures.

For example, instead of applying HRW to all 108 real nodes in the diagram, we can first apply HRW to the 27 lowest-tier virtual nodes, selecting one. We then apply HRW to the four real nodes in its cluster, and choose the winning site. We only need hashes, rather than 108. If we apply this method starting one level higher in the hierarchy, we would need hashes to get to the winning site. The figure shows how, if we proceed starting from the root of the skeleton, we may successively choose the virtual nodes , , and , and finally end up with site 74.

The virtual hierarchy need not be stored, but can be created on demand, since the virtual nodes names are simply prefixes of base- (or mixed-radix) representations. We can easily create appropriately sorted strings from the digits, as required. In the example, we would be working with the strings (at tier 1), (at tier 2), and (at tier 3). Clearly, has height , since and are both constants. The work done at each level is , since is a constant.

The value of can be chosen based on factors like the anticipated failure rate and the degree of desired load balancing. A higher value of leads to less load skew in the event of failure at the cost of higher search overhead.

The choice is equivalent to non-hierarchical rendezvous hashing. In practice, the hash function is very cheap, so can work quite well unless is very high.

For any given object, it is clear that each leaf-level cluster, and hence each of the sites, is chosen with equal probability.

Replication, site failures, and site additions One can enhance resiliency to failures by replicating each object O across the highest ranking r < m sites for O, choosing r based on the level of resiliency desired. The simplest strategy is to replicate only within the leaf-level cluster.

If the leaf-level site selected for O is unavailable, we select the next-ranked site for O within the same leaf-level cluster. If O has been replicated within the leaf-level cluster, we are sure to find O in the next available site in the ranked order of r sites. All objects that were held by the failed server appear in some other site in its cluster. (Another option is to go up one or more tiers in the skeleton and select an alternate from among the sibling virtual nodes at that tier. We then descend the hierarchy to the real nodes, as above.)

When a site is added to the system, it may become the winning site for some objects already assigned to other sites. Objects mapped to other clusters will never map to this new site, so we need to only consider objects held by other sites in its cluster. If the sites are caches, attempting to access an object mapped to the new site will result in a cache miss, the corresponding object will be fetched and cached, and operation returns to normal.

If sites are servers, some objects must be remapped to this newly added site. As before, objects mapped to other clusters will never map to this new site, so we need to only consider objects held by sites in its cluster. That is, we need only remap objects currently present in the m sites in this local cluster, rather than the entire set of objects in the system. New objects mapping to this site will of course be automatically assigned to it.

Comparison with consistent hashing Because of its simplicity, lower overhead, and generality (it works for any k < n), rendezvous hashing is increasingly being preferred over consistent hashing. Recent examples of its use include the GitHub load balancer, the Apache Ignite distributed database, and by the Twitter EventBus pub/sub platform.

Consistent hashing operates by mapping each site uniformly and randomly to multiple points on a unit circle called tokens. Objects are also mapped to the unit circle and placed in the site owning the token that is first encountered traveling clockwise from the object's location. When a site is removed, each of its objects is transferred to the site owning the next token encountered moving clockwise. Provided each site is mapped to a large number of tokens (100–200, say), this will reassign objects in a relatively uniform fashion among the remaining sites.

If a site's tokens are placed on the unit circle by hashing 200 variants of the site ID, say, then the assignment of any object requires storing or recalculating 200 hash values for each site. However, the tokens associated with a given site can be precomputed and stored in a sorted list, requiring only a single application of the hash function to the object, and a binary search to compute the assignment. Even with many tokens per site, however, the basic version of consistent hashing may not balance objects uniformly over sites, since when a site is removed each object assigned to it is distributed only over as many other sites as the site has tokens (say 100–200).

Variants of consistent hashing (such as Amazon's Dynamo) that use more complex logic to distribute tokens on the unit circle offer better load balancing than basic consistent hashing, reduce the overhead of adding new sites, and reduce metadata overhead and offer other benefits.

Advantages of Rendezvous hashing over consistent hashing