HashRing

Struct HashRing 

Source
pub struct HashRing<T, S = DefaultHashBuilder> { /* private fields */ }
Expand description

HashRing represents a set of nodes (cluster) that shall use consistent hashing HashRing provides methods to add and remove nodes to the cluster HashRing can calculate for each node which hashranges they are responsible for HashRing can calculate replication instructions if a cluster changes or if the cluster if replaced completely to find target nodes and source nodes with affected hashranges

Implementations§

Source§

impl<T> HashRing<T>
where T: Hash + Clone + Debug + PartialEq,

Source

pub fn get_hash_ranges(&self) -> Vec<Replicas<T>>

Source

pub fn find_sources( &self, target: &T, source: &HashRing<T>, available_nodes: &[T], ) -> Vec<Replicas<T>>

for given node: Node calculate all available source Nodes that can provide keys which need to be stored on the given node (after a change of the given cluster) for general replication instructions within the cluster, use fn get_hash_ranges() available nodes provides all nodes that can be used to replicate keys from this covers different scenarios:

  1. self (this HashRing) and source cover the same deployment of one cluster, containing nodes that left or joined the ring
  2. self (this HashRing) and source cover the same deployment of one cluster, containing some nodes that are terminating currently (available to sync from, but should not receive new keys)
  3. source refering to the original deployment and self (this HashRing) refering to the replacement deployment, therefor available_nodes refering to the original deployment
§Arguments
  • target - return replication sources for this node. target needs to be member of the current HashRing
  • source - find replication nodes within this HashRing
  • available_nodes - define all nodes that can be used for replication in source HashRing
§Examples
use std::hash::{Hash, Hasher};
use std::net::Ipv4Addr;
use std::str::FromStr;

use hashring_coordinator::HashRing;

#[derive(Debug, Copy, Clone, PartialEq)]
struct Node {
    addr: Ipv4Addr,
}

impl Node {
    fn new(ip: &str) -> Self {
        let addr = Ipv4Addr::from_str(ip).unwrap();
        Node { addr }
    }
}

impl Hash for Node {
    fn hash<H: Hasher>(&self, s: &mut H) {
        (self.addr).hash(s)
    }
}
  

let node1 = Node::new("127.0.0.1"); // hash @1093046220658055553
let node2 = Node::new("127.0.0.2"); // hash @7508079630756128442
let node3 = Node::new("127.0.0.3"); // hash @12322253174093194230

let nodes_original = vec![node1, node2];
let mut ring_original = HashRing::new(0, 1);

ring_original.batch_add(nodes_original.clone());

let mut ring_new = ring_original.clone();
ring_new.add(node3.clone());

// sources contains a list with hashranges and target nodes that can be synchronized to node3
// sources = [Replicas { hash_range: 7508079630756128443..=12322253174093194230, nodes: [Node { addr: 127.0.0.1 }] }]
// node3 was added, thus the hashrange between node2 and node3 which was located on node1 so far can be moved over to node3
let sources = ring_new.find_sources(&node3, &ring_original, &nodes_original);

Source

pub fn merge_replicas(&self, replicas: Vec<Replicas<T>>) -> Vec<Replicas<T>>

merge hashranges together, if the hashrange touch and all affected nodes are identical

Source

pub fn hash_nodes(&self, nodes: &Vec<T>) -> u64

Source§

impl<T, S> HashRing<T, S>
where T: Hash + Clone + Debug + PartialEq, S: BuildHasher,

Source

pub fn add(&mut self, node: T)

Add node to the hash ring.

Source

pub fn batch_add(&mut self, nodes: Vec<T>)

Source

pub fn remove(&mut self, node: &T)
where T: PartialEq,

Remove node from the hash ring.

Source

pub fn get<U: Hash>(&self, key: &U) -> Vec<T>

returns all real nodes responsible for key

Returns an empty array if the ring is empty

Source

pub fn get_hash<U>(&self, input: &U) -> u64
where U: Hash,

returns the hash for a given key or node (as used in this HashRing)

Source

pub fn nodes(&self) -> Vec<T>

Source§

impl<T> HashRing<T>

Hash Ring

A hash ring that provides consistent hashing for nodes that are added to it.

Source

pub fn new(replicas: usize, vnodes: usize) -> HashRing<T>

Create a new HashRing.

§Arguments
  • replicas - number of nodes to store copies of each key (set replicas to 0, to store each key only once)
  • vnodes - number of virtual nodes per real node in the cluster (higher number means more even distribution of keys across all nodes, but higher processing effort)
Source§

impl<T, S> HashRing<T, S>

Source

pub fn len(&self) -> usize

Get the number of real nodes in the hash ring.

Source

pub fn vlen(&self) -> usize

Get the number of virtual nodes in the hash ring.

Source

pub fn is_empty(&self) -> bool

Returns true if the ring has no elements.

Source

pub fn with_hasher( replicas: usize, vnodes: usize, hash_builder: S, ) -> HashRing<T, S>

Creates an empty HashRing which will use the given hash builder.

§Arguments
  • replicas - number of nodes to store copies of each key (set replicas to 0, to store each key only once)
  • vnodes - number of virtual nodes per real node in the cluster (higher number means more even distribution of keys across all nodes, but higher processing effort)
  • hash_builder - implementation of BuildHasher to provider a Hasher for the HashRing
§Examples
use hashring_coordinator::HashRing;
use siphasher::sip::SipHasher;
use std::hash::{BuildHasher, Hash, Hasher};

#[derive(Clone, PartialEq, Debug)]
pub struct DefaultHashBuilder;

impl BuildHasher for DefaultHashBuilder {
    type Hasher = SipHasher;

    fn build_hasher(&self) -> Self::Hasher {
        SipHasher::new()
    }
}

struct Node {}
impl Hash for Node {
    fn hash<H: Hasher>(&self, s: &mut H) {
        todo!()
    }
}

let hash_builder = DefaultHashBuilder {};
let mut ring: HashRing<Node, DefaultHashBuilder> = HashRing::with_hasher(2, 100, hash_builder);

Trait Implementations§

Source§

impl<T: Clone, S: Clone> Clone for HashRing<T, S>

Source§

fn clone(&self) -> HashRing<T, S>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug, S: Debug> Debug for HashRing<T, S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Default for HashRing<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'a, T> IntoIterator for &'a HashRing<T>

Source§

type Item = &'a T

The type of the elements being iterated over.
Source§

type IntoIter = HashRingRefIterator<'a, T>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T> IntoIterator for HashRing<T>

Source§

type Item = T

The type of the elements being iterated over.
Source§

type IntoIter = HashRingIterator<T>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T: PartialEq, S: PartialEq> PartialEq for HashRing<T, S>

Source§

fn eq(&self, other: &HashRing<T, S>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T, S> StructuralPartialEq for HashRing<T, S>

Auto Trait Implementations§

§

impl<T, S> Freeze for HashRing<T, S>
where S: Freeze,

§

impl<T, S> RefUnwindSafe for HashRing<T, S>

§

impl<T, S> Send for HashRing<T, S>
where S: Send, T: Send,

§

impl<T, S> Sync for HashRing<T, S>
where S: Sync, T: Sync,

§

impl<T, S> Unpin for HashRing<T, S>
where S: Unpin, T: Unpin,

§

impl<T, S> UnwindSafe for HashRing<T, S>
where S: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.