ExRingRing (ExRingRing v0.1.1)

Copy Markdown View Source

ExRingRing - Consistent Hash Ring implementation in Elixir.

This module provides the main public API for creating and manipulating consistent hash rings.

Example

# Create nodes
nodes = ExRingRing.list_to_nodes([:a, :b, :c, :d, :e])

# Create a ring
ring = ExRingRing.make(nodes)

# Find a node for an item
{:ok, node} = ExRingRing.find_node(ring, "item_1")

# Collect multiple nodes for replication
nodes = ExRingRing.collect_nodes(ring, "item_1", 3)

# Add a node
new_ring = ExRingRing.add_node(ring, ExRingRing.Domain.Entities.Node.make(:f))

# Remove a node
new_ring = ExRingRing.remove_node(ring, :c)

Summary

Functions

Adds a single node to the ring.

Adds nodes to the ring.

Collects N nodes for the given item in order of priority.

Finds the node responsible for the given item.

Gets the number of nodes in the ring.

Gets all nodes in the ring as a list.

Checks if the given term is a valid ring.

Converts a list of keys/tuples to a list of nodes.

Creates a new consistent hash ring.

Creates a new consistent hash ring from a list of keys.

Removes a single node from the ring.

Removes nodes from the ring by their keys.

Functions

add_node(ring, node)

Adds a single node to the ring.

add_nodes(ring, nodes)

Adds nodes to the ring.

Existing nodes with the same key will be overwritten.

collect_nodes(ring, item, count)

Collects N nodes for the given item in order of priority.

Useful for replication - the first node is primary, subsequent nodes are replicas.

find_node(ring, item)

@spec find_node(ExRingRing.Domain.Entities.Ring.t(), term()) ::
  {:ok, ExRingRing.Domain.Entities.Node.t()} | :error

Finds the node responsible for the given item.

Returns {:ok, node} or :error if the ring is empty.

get_node_count(ring)

@spec get_node_count(ExRingRing.Domain.Entities.Ring.t()) :: non_neg_integer()

Gets the number of nodes in the ring.

get_nodes(ring)

Gets all nodes in the ring as a list.

is_ring(ring)

@spec is_ring(term()) :: boolean()

Checks if the given term is a valid ring.

list_to_nodes(list)

@spec list_to_nodes([term()]) :: [ExRingRing.Domain.Entities.Node.t()]

Converts a list of keys/tuples to a list of nodes.

Accepts:

  • Keys: [:a, :b, :c]
  • Key-data pairs: [{:a, "data_a"}, {:b, "data_b"}]
  • Key-data-options tuples: [{:a, "data_a", [weight: 2]}, {:b, "data_b"}]

Examples

iex> ExRingRing.list_to_nodes([:a, :b, :c]) |> length()
3

iex> ExRingRing.list_to_nodes([{:a, "server_a"}, {:b, "server_b", [weight: 2]}]) |> length()
2

make(nodes, opts \\ [])

Creates a new consistent hash ring.

Options

  • :virtual_node_count - Number of virtual nodes per physical node (default: 256)
  • :max_hash_byte_size - Maximum bytes of hash to use (default: 4)
  • :hash_algorithm - Hash algorithm: :md5, :sha, :sha256, :crc32, :phash2 (default: :md5)
  • :implementation - Ring implementation: :static (fast reads) or :dynamic (fast writes) (default: :static)

Examples

iex> nodes = ExRingRing.list_to_nodes([:a, :b, :c])
iex> ring = ExRingRing.make(nodes)
iex> ExRingRing.is_ring(ring)
true

iex> ring = ExRingRing.make_from_keys([:a, :b, :c], virtual_node_count: 128)
iex> ExRingRing.is_ring(ring)
true

make_from_keys(keys, opts \\ [])

@spec make_from_keys(
  [term()],
  keyword()
) :: ExRingRing.Domain.Entities.Ring.t()

Creates a new consistent hash ring from a list of keys.

Examples

iex> ring = ExRingRing.make_from_keys([:a, :b, :c])
iex> ExRingRing.is_ring(ring)
true

remove_node(ring, key)

Removes a single node from the ring.

remove_nodes(ring, keys)

Removes nodes from the ring by their keys.