内容: 借用极客时间github上的例子来呈现一致性哈希在扩展时减少的压力
一、普通哈希的情况:
package main
import (
"flag"
"fmt"
)
var keysPtr = flag.Int("keys", 10000000, "key number")
var nodesPtr = flag.Int("nodes", 3, "node number of old cluster")
var newNodesPtr = flag.Int("new-nodes", 4, "node number of new cluster")
func hash(key int, nodes int) int {
return key % nodes
}
func main() {
flag.Parse()
var keys = *keysPtr
var nodes = *nodesPtr
var newNodes = *newNodesPtr
migrate := 0
for i := 0; i < keys; i++ {
if hash(i, nodes) != hash(i, newNodes) {
migrate++
}
}
migrateRatio := float64(migrate) / float64(keys)
fmt.Printf("%f%%\n", migrateRatio*100)
}
测试数据:
1、三个站点迁移到四个站点时,需要修改的信息量:基本有75%需要迁移
2、四个站点迁移到五个站点呢?五个到六个呢?:基本有80%需要迁移
3、那么十五个到十六个呢?那么五十个到五十一个呢?:基本都需要迁移
结果分析:普通哈希映射,当前站点越多,出现站点变更时,需要重映射的数据量更大
二、一致性哈希的情况
package main
import (
"flag"
"fmt"
"log"
"stathat.com/c/consistent"
"strconv"
)
var keysPtr = flag.Int("keys", 10000, "key number")
var nodesPtr = flag.Int("nodes", 3, "node number of old cluster")
var newNodesPtr = flag.Int("new-nodes", 4, "node number of new cluster")
func hash(key int, nodes int) int {
return key % nodes
}
func main() {
flag.Parse()
var keys = *keysPtr
var nodes = *nodesPtr
var newNodes = *newNodesPtr
c := consistent.New()
for i := 0; i < nodes; i++ {
c.Add(strconv.Itoa(i))
}
newC := consistent.New()
for i := 0; i < newNodes; i++ {
newC.Add(strconv.Itoa(i))
}
migrate := 0
for i := 0; i < keys; i++ {
server, err := c.Get(strconv.Itoa(i))
if err != nil {
log.Fatal(err)
}
newServer, err := newC.Get(strconv.Itoa(i))
if err != nil {
log.Fatal(err)
}
if server != newServer {
migrate++
}
}
migrateRatio := float64(migrate) / float64(keys)
fmt.Printf("%f%%\n", migrateRatio*100)
}
测试与普通哈希一样的数据:
还有很多很多组数据
…
…
测试结果:基本上都是当前站点越多,迁移时,采用一致性哈希,迁移成本越低。
代码参考处:https://github.com/hanj4096/hash (出自极客时间某位分布式老师)
大四学生一枚,如果文章有错误的地方,欢迎在下方提出,每条评论我都会去认真看并回复,同时感谢指正的前辈。有喜欢C/C++,linux的同学欢迎私信一起讨论学习。