Skip to content

Instantly share code, notes, and snippets.

@mfurquimdev
Last active August 4, 2019 02:10
Show Gist options
  • Select an option

  • Save mfurquimdev/54ecf6d4dbd3d66c5739c8eb142a1780 to your computer and use it in GitHub Desktop.

Select an option

Save mfurquimdev/54ecf6d4dbd3d66c5739c8eb142a1780 to your computer and use it in GitHub Desktop.
Testing hashring function with and without hash.
package main
import (
"crypto/sha512"
"fmt"
"github.com/serialx/hashring"
"math/rand"
"time"
)
func main() {
// If nodes are small hashring.New(nodes).GetNode(key) always return the last node in list
fmt.Printf("If nodes are small hashring.New(nodes).GetNode(key) always return the last node in list\n")
nodes := []string{"e", "m", "v"}
keys := []string{"a", "i", "q", "z"}
printNodeKey(nodes, keys)
for t := 0; t < 2; t++ {
nodes = shuffleList(nodes)
keys = shuffleList(keys)
printNodeKey(nodes, keys)
}
// If nodes are too orderly, hashring.New(nodes).GetNode(key) always return the same key regardless of the order
fmt.Printf("\n\nIf nodes are too orderly, hashring.New(nodes).GetNode(key) always return the same key regardless of the order\n")
nodes = []string{"172.17.233.227:43001", "172.17.234.52:43002", "172.30.228.167:43003"}
keys = []string{"172.17.234.44:43001", "172.17.233.252:43002", "172.17.233.249:43003", "172.17.234.67:43004"}
printNodeKey(nodes, keys)
for t := 0; t < 2; t++ {
nodes = shuffleList(nodes)
keys = shuffleList(keys)
printNodeKey(nodes, keys)
}
// Solved it by hashing the IP
fmt.Printf("\n\nSolved it by hashing the IP\n")
for t := 0; t < 2; t++ {
nodes = shuffleList(nodes)
keys = shuffleList(keys)
printHashedNodeKey(nodes, keys)
}
}
func hashList(list []string) []string {
hashedList := make([]string, 0)
for _, item := range list {
hash := hashString(item)
hashedList = append(hashedList, hash)
}
return hashedList
}
func hashString(str string) string {
hashedByte := sha512.Sum384([]byte(str))
hashedString := string(hashedByte[:])
return hashedString
}
func shuffleList(list []string) []string {
dest := make([]string, len(list))
rand.Seed(time.Now().UnixNano())
perm := rand.Perm(len(list))
for i, v := range perm {
dest[v] = list[i]
}
return dest
}
func printHashedNodeKey(nodes, keys []string) {
hashedNodes := hashList(nodes)
ring := hashring.New(hashedNodes)
fmt.Printf("nodes = %s\nkeys = %s\n{\n", nodes, keys)
for _, key := range keys {
hNode, _ := ring.GetNode(hashString(key))
for _, node := range nodes {
if hashString(node) == hNode {
fmt.Printf(" %s -> %s\n", key, node)
break
}
}
}
fmt.Printf("}\n\n")
}
func printNodeKey(nodes, keys []string) {
ring := hashring.New(nodes)
fmt.Printf("nodes = %s\nkeys = %s\n{\n", nodes, keys)
for _, key := range keys {
node, _ := ring.GetNode(key)
fmt.Printf(" %s -> %s\n", key, node)
}
fmt.Printf("}\n\n")
}
@flaviostutz
Copy link
Copy Markdown

Did this improve the balancing when using sequential IPs?

@mfurquimdev
Copy link
Copy Markdown
Author

Yes, the hashing did improve the balancing when using any IP. I will make another gist testing multiple hashing later.

@flaviostutz
Copy link
Copy Markdown

flaviostutz commented Aug 4, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment