很早就听说过A*算法,据说在寻路径时,是一种比较高效的算法。但是一直没有搞清楚原理。 这段时间刚好有个营救公主的例子: 题描述 : 公主被魔王抓走了 , 王子需要拯救出美丽的公主 。 他进
顺晟科技
2021-08-28 09:41:30
359
一致性散列算法在分布式应用中被广泛使用。主要作用是解决服务的热点问题。例如,在分布式数据存储(如Redis缓存集、状态活动等)中,可以解决请求的热点问题,并缓解服务更改时出现的负载不平衡。
本文简要介绍一致性散列算法,并分析golang的开放源代码实现包(github.com/stathat/consistent)
一致性哈希算法原理
解决的问题
分布式存储通常首先在代理层执行hash,以确保不同系统缓存的数据平衡和负载平衡。一般来说,我们会做模具工作,并将服务分配给其他机器。但是,在这种情况下,如果服务关闭或新系统加入,将直接影响所有系统的缓存。为了解决这个问题,出现了一致性哈希算法。
如何解决
一致性散列算法主要用于解决散列后将值映射到已设置系统的方法。下面是散列阶段。
1.将散列值组织成圆环。通常为[0,2 32-1] 2。均匀选择圆环上的Hash点作为系统的节点。3.访问机器时,Hash接触到圆环上的一点。顺时针访问的个节点是需要访问的机器
这样,当一台机器停机时,停机机器的下一台机器将委托停机机器的存储工作。将系统节点添加到Hash环路中的两个系统节点后,原始节点存储操作将被分为新添加的节点上的部分存储操作。
升华
一般来说,使用上述一致性哈希算法,发生停机时,一台机器做两台机器工作显然是不科学的。因此,虚拟节点的概念也是必需的。将虚拟节点放置在循环中,然后实际服务节点维护多个虚拟节点。此外,一个服务节点的多个虚拟节点必须单独分布。这样,当一个服务节点停机时,多个单独的虚拟节点将从散列循环中消失,这样,正常的系统就可以在保留现有数据的同时,承载停机时间对应的单独节点的负载。
一致哈希算法的golang实现
Github.com/stathat/consistent是golang实施的一致散列算法。
数据结构
在实现中,在分布式缓存中添加了更有用的副本概念。结构如下:
Type Consistent struct {
circle map[uint 32]字串//储存环
Members map[string]bool //成员标记
sorted hashes uints/[]int 32类型显示环的虚拟节点,排序的slice
NumberOfReplicas int //副本数
Count int64 //节点数
划痕[64]字节//未使用
UseFnv bool //标记使用FNV-1a hash
Sync .RWMutex //读写锁定标记
}
设置节点
初始化节点时,必须提供每个节点的名称和副本数。初始化将执行以下任务:
将Hash和node名称之间的映射保存在circle中
将Members显示为true
将散列值放入已排序的sorted hash中
func(c * consistent)set(elts[]string){
C.Lock()
Defer c.Unlock()
For k :=range c.members {//首先删除elts集合中没有的数据
Found :=false
For _,v :=range elts {
If k==v {
Found=true
布雷克
}
}
If!Found {
C.remove(k)
}
}
For _,v :=范围elts {//后面依次添加
_,exists 3360=c . members[v]
If exists {
Continue
}
C.add(v)
}
}
Func (c *一致性)add (ELT string) {
FOR I :=0;I c . NumberOfReplicasI {
c . circle[c . hash key(c . ELT key(ELT,I)]=ELT
}
C.members[elt]=true
更新c . updatesortedhashes()//sorted hashes字段以确认顺序
C.count
}
访问
通过Name映射node时,首先计算hash值,然后通过二进制查找方法从sortedHashes slice中获取该node的hash值,再通过circle映射该node name。
Func (c *一致性)get(名称字符串) (字符串,错误){
C.RLock()
Defer c.RUnlock()
If len(c.circle)==0 {
Return ' ',ErrEmptyCircle
}
密钥3360=C .散列密钥(name)
I:=c.search(键)
return c . circle[c . sorted hashes[I],nil
}
删除
一个系统停机后,可以删除该节点节点,快速调整服务请求。
Func (c *一致性)remove (ELT string) {
//代码有锁
FOR I :=0;I c . NumberOfReplicasI {
删除(C. circle,C. hash key (C. ELT key (ELT,I)))
}
删除(C. members,ELT)
C.updateSortedHashes()
C.count -
}
摘要
在代码实现中,我们可以看到:
要在环形中找到下一个节点,只需将所有节点的哈希值存储在有序切片中,然后进行平分查询即可。为了保持每个节点数据的平衡,通常会添加更多的虚拟节点,为了保证访问请求的速度,不能添加太多的虚拟节点。例如,在Codis上,虚拟节点默认设置为1024个(当然,还可以配置更多插槽)。
调整一致性散列服务时,可能会过度平滑
分布式缓存服务Redis-Cluster、Codis比较常见的应用程序或服务代理twemproxy等。
28
2021-08
28
2021-08
28
2021-08
28
2021-08
28
2021-08
28
2021-08