Hashing por módulo (key % N) quebra feio quando o N muda: trocar o número de servidores remapeia quase tudo. Consistent hashing põe nós e chaves no mesmo anel e só mexe numa fração quando a topologia muda. Mexe nos nós aqui embaixo e olha o contador.
◆ losango = nó (vnode)chave (cor = nó dono)contorno branco = movida agora
Operação
Custo
Lookup (chave → nó)
O(log n)
Add/remove nó
~K/n chaves movem
Por módulo (comparação)
~quase K movem
Cada chave pertence ao primeiro nó no sentido horário do anel. Adicionar ou remover um nó mexe só nas chaves daquele trecho, perto de K/n, e deixa o resto parado. Por isso consistent hashing segura cache distribuído e sharding sem derrubar o backend a cada mudança de topologia. Os virtual nodes (vnodes) espalham cada nó físico em vários pontos pra equilibrar a carga.
O ring em Go
typeRingstruct {
hashes []uint32// vnodes ordenados
nodes map[uint32]string// hash -> nó
vnodes int
}
func (r *Ring) Add(node string) {
for i := 0; i < r.vnodes; i++ {
h := hash(fmt.Sprintf("%s#%d", node, i))
r.hashes = append(r.hashes, h)
r.nodes[h] = node
}
sort.Slice(r.hashes, func(i, j int) bool {
return r.hashes[i] < r.hashes[j]
})
}
func (r *Ring) Get(key string) string {
iflen(r.hashes) == 0 { return"" }
h := hash(key)
// 1º vnode com hash >= h (busca binária do módulo 02)
i := sort.Search(len(r.hashes), func(i int) bool {
return r.hashes[i] >= h
})
if i == len(r.hashes) { i = 0 } // wrapreturn r.nodes[r.hashes[i]]
}
🧠 Desafio — Consistent Hashing
Brinca com o anel aqui de cima antes de responder. As duas últimas são de reflexão: escreve a sua e só então revela o modelo.
🔧 Prática — ache o bug
Esse roteador de cache distribuído tem um problema sério ao escalar. Clica na linha do bug.