consistent_hashing

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2024 License: MIT Imports: 10 Imported by: 0

README


Consistent-Hashing

Consistent-Hashing is a Go library designed for distributed load balancing using consistent hashing, enhanced with bounded loads. It provides efficient key distribution across a set of hosts while ensuring that no single host becomes overloaded beyond a specified limit.

Installation

To install the package, execute the following command:

go get github.com/ArchishmanSengupta/consistent-hashing

Usage

Here's a straightforward example of how to utilize the consistent_hashing package:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/ArchishmanSengupta/consistent-hashing"
)

func main() {
	// Create a new ConsistentHashing instance with default configuration
	ch, err := consistent_hashing.NewWithConfig(consistent_hashing.Config{})
	if err != nil {
		log.Fatal(err)
	}

	// Add hosts to the consistent hash ring
	hosts := []string{"host1", "host2", "host3", "host4"}
	ctx := context.Background()
	for _, host := range hosts {
		err := ch.Add(ctx, host)
		if err != nil {
			log.Printf("Error adding host %s: %v", host, err)
		}
	}

	// Distribute some keys
	keys := []string{"key1", "key2", "key3", "key4", "key5"}
	for _, key := range keys {
		host, err := ch.GetLeast(ctx, key)
		if err != nil {
			log.Printf("Error getting host for key %s: %v", key, err)
			continue
		}
		fmt.Printf("Key %s assigned to host %s\n", key, host)
		
		// Increase the load for the assigned host
		err = ch.IncreaseLoad(ctx, host)
		if err != nil {
			log.Printf("Error increasing load for host %s: %v", host, err)
		}
	}

	// Print current loads
	loads := ch.GetLoads()
	fmt.Println("Current loads:")
	for host, load := range loads {
		fmt.Printf("%s: %d\n", host, load)
	}

	// Remove a host from the ring
	hostToRemove := "host2"
	err = ch.Remove(ctx, hostToRemove)
	if err != nil {
		log.Printf("Error removing host %s: %v", hostToRemove, err)
	}

	// Print updated list of hosts
	fmt.Println("Remaining hosts after removal:", ch.Hosts())
}

Output

Key key1 assigned to host host4
Key key2 assigned to host host3
Key key3 assigned to host host2
Key key4 assigned to host host1
Key key5 assigned to host host4
Current loads:
host2: 1
host3: 1
host4: 2
host1: 1
Remaining hosts after removal: [host1 host3 host4]

Features

  • Consistent Hashing with Bounded Loads: Distributes load evenly across hosts while limiting maximum host load.
  • Customizable Configuration: Adjust replication factor, load factor, and hash function to suit specific requirements.
  • Thread-Safe Operations: Ensures safe concurrent access for adding hosts, distributing keys, and managing loads.
  • Efficient Key Distribution: Uses consistent hashing principles for efficient key assignment and lookup.

Configuration

Customize consistent hashing behavior by providing a Config struct during instance creation:

cfg := consistent_hashing.Config{
    ReplicationFactor: 20,    // Number of virtual nodes per host
    LoadFactor:        1.25,  // Maximum load factor before redistribution
    HashFunction:      fnv.New64a, // Custom hash function (optional)
}

ch, err := consistent_hashing.NewWithConfig(cfg)

Benchmarking

Use the following command to run benchmarks:

go test -bench=. -benchmem

Example benchmark results:

goos: darwin
goarch: arm64
pkg: github.com/ArchishmanSengupta/consistent-hashing
BenchmarkAdd-10                             4626          19088168 ns/op           23748 B/op        895 allocs/op
BenchmarkGet-10                          6359968               186.5 ns/op            47 B/op          4 allocs/op
BenchmarkGetLeast-10                         180           6606643 ns/op              24 B/op          3 allocs/op
BenchmarkIncreaseLoad-10                13727469                83.96 ns/op           13 B/op          1 allocs/op
BenchmarkRemove-10                           139           8671612 ns/op           17696 B/op       1306 allocs/op
BenchmarkParallelOperations-10               884           1297025 ns/op             123 B/op          9 allocs/op
PASS
ok      github.com/ArchishmanSengupta/consistent-hashing        160.723s

API Reference

Methods
  • NewWithConfig(cfg Config) (*ConsistentHashing, error): Creates a new instance of ConsistentHashing with specified configuration.
  • Add(ctx context.Context, host string) error: Adds a new host to the consistent hash ring.
  • Get(ctx context.Context, key string) (string, error): Retrieves the host responsible for a given key.
  • GetLeast(ctx context.Context, key string) (string, error): Retrieves the least loaded host for a given key.
  • IncreaseLoad(ctx context.Context, host string) error: Increases the load for a specified host.
  • DecreaseLoad(ctx context.Context, host string) error: Decreases the load for a specified host.
  • GetLoads() map[string]int64: Retrieves the current load for all hosts.
  • Hosts() []string: Retrieves the list of all hosts in the ring.
  • Remove(ctx context.Context, host string) error: Removes a host from the ring.

Examples

Adding and Removing Hosts
ch, _ := consistent_hashing.NewWithConfig(consistent_hashing.Config{})
ctx := context.Background()

// Adding hosts
ch.Add(ctx, "host1")
ch.Add(ctx, "host2")
ch.Add(ctx, "host3")

// Removing a host
err := ch.Remove(ctx, "host2")
if err != nil {
    log.Printf("Error removing host: %v", err)
}

fmt.Println("Current hosts:", ch.Hosts())
Distributing Keys with Load Balancing
ch, _ := consistent_hashing.NewWithConfig(consistent_hashing.Config{})
ctx := context.Background()

// Add hosts
for i := 1; i <= 5; i++ {
    ch.Add(ctx, fmt.Sprintf("host%d", i))
}

// Distribute keys
keys := []string{"user1", "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "user10"}
for _, key := range keys {
    host, _ := ch.GetLeast(ctx, key)
    fmt.Printf("Key %s assigned to %s\n", key, host)
    ch.IncreaseLoad(ctx, host)
}

// Print final loads
loads := ch.GetLoads()
for host, load := range loads {
    fmt.Printf("%s load: %d\n", host, load)
}

Contributing

Contributions are welcome! Feel free to submit a Pull Request with your enhancements or bug fixes.


This README now includes detailed instructions on adding, removing hosts, and showcases example usage scenarios for distributing keys and benchmarking performance. It should provide comprehensive guidance for users looking to integrate and leverage the Consistent-Hashing library effectively.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoHost       = errors.New("no host added")
	ErrHostNotFound = errors.New("host not found")
)

Custom errors

Functions

This section is empty.

Types

type Config

type Config struct {
	ReplicationFactor int                // no of virtual_nodes per host
	LoadFactor        float64            // max load factor before redistribution
	HashFunction      func() hash.Hash64 // for the time being lets keep the hash function simple
}

Consistent Hashing config parameters

type ConsistentHashing

type ConsistentHashing struct {
	// contains filtered or unexported fields
}

CH with bounded loads

func NewWithConfig

func NewWithConfig(cfg Config) (*ConsistentHashing, error)

New CH instance

func (*ConsistentHashing) Add

func (c *ConsistentHashing) Add(ctx context.Context, host string) error

Add adds a new host to the consistent hashing ring, including its virtual nodes, and updates the internal data structures accordingly. It returns an error if the operation fails.

func (*ConsistentHashing) DecreaseLoad

func (c *ConsistentHashing) DecreaseLoad(ctx context.Context, host string) error

DecreaseLoad decreases the Load for a specific host.

func (*ConsistentHashing) Get

func (c *ConsistentHashing) Get(ctx context.Context, key string) (string, error)

Get retrieves the host that should handle the given key in the consistent hashing ring. It returns the host name and nil error if successful. If no hosts are added, it returns ErrNoHost. If there's an error generating the hash value or searching for it, it returns an appropriate error. If the host associated with the hash value is not found, it returns ErrHostNotFound.

func (*ConsistentHashing) GetLeast

func (c *ConsistentHashing) GetLeast(ctx context.Context, key string) (string, error)

GetLeast retrieves the host that should handle the given key in the consistent hashing ring with the least current load. It returns the host name and nil error if successful. If no hosts are added, it returns ErrNoHost. If there's an error generating the hash value or searching for it, it returns an appropriate error. If no host with acceptable load is found, it falls back to returning the initially found host. If no suitable host is found at all, it returns ErrHostNotFound. Bounded Loads: Research Paper: https://research.googleblog.com/2017/04/consistent-hashing-with-bounded-loads.html

func (*ConsistentHashing) GetLoads

func (c *ConsistentHashing) GetLoads() map[string]int64

GetLoads returns the current load for all hosts

func (*ConsistentHashing) Hash

func (c *ConsistentHashing) Hash(key string) (uint64, error)

hash generates a 64-bit hash value for a given key using the configured hash function. It returns the computed hash value and an error, if any occurred during the hashing process.

func (*ConsistentHashing) Hosts

func (c *ConsistentHashing) Hosts() []string

Hosts returns the list of current hosts

func (*ConsistentHashing) IncreaseLoad

func (c *ConsistentHashing) IncreaseLoad(ctx context.Context, host string) error

IncreaseLoad increments the load for a specific host.

func (*ConsistentHashing) LoadOk

func (c *ConsistentHashing) LoadOk(host string) bool

LoadOk checks if the host's current load is below the maximum allowed load. It returns true if the host's load is acceptable, otherwise false.

func (*ConsistentHashing) MaxLoad

func (c *ConsistentHashing) MaxLoad() int64

MaxLoad calculates and returns the maximum allowed load per host based on the current total load across all hosts and the configured load factor.

func (*ConsistentHashing) Remove

func (c *ConsistentHashing) Remove(ctx context.Context, host string) error

Remove removes a host from the hash ring

func (*ConsistentHashing) Search

func (c *ConsistentHashing) Search(key uint64) (int, error)

Search finds the closest index in the sorted set where the given hash key should be placed. It uses binary search to efficiently locate the index. For example, if c.sortedSet = [10, 20, 30, 40, 50] and key = 25, sort.Search determines that key should be inserted after 20 and before 30, returning index 2. The modulo operation (index % len(c.sortedSet)) ensures correct placement within the ring structure

func (*ConsistentHashing) UpdateLoad

func (c *ConsistentHashing) UpdateLoad(ctx context.Context, host string, load int64) error

UpdateLoad updates the load for a specific host

type Host

type Host struct {
	Name string // HostName or identifier
	Load int64  // current load on the host
}

Host is a physical node in the CH hashing ring

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL