Avançar para o conteúdo principal

Consistent Hashing

Consistent Hashing

Consistent hashing é um conceito fundamental em sistemas distribuídos para distribuir dados de forma uniforme entre múltiplos servidores enquanto minimiza a necessidade de reorganização dos dados quando os servidores são adicionados ou removidos da rede. Esse método é amplamente utilizado em caches distribuídos, bancos de dados distribuídos, sistemas de armazenamento de arquivos e balanceamento de carga, entre outros.

Princípios Básicos do Consistent Hashing:

  1. Círculo de Hash: O espaço de hash é imaginado como um círculo (ou anel), com cada servidor e cada chave de dados mapeados para um ponto no círculo usando uma função de hash.
  2. Mapeamento de Chaves: Cada dado (como uma chave de cache ou uma chave de banco de dados) é mapeado para um ponto no círculo de hash usando a mesma função de hash. Isso determina qual servidor será responsável por armazenar ou processar essa chave.
  3. Redistribuição Balanceada: Quando um servidor é adicionado ou removido do sistema, apenas uma fração mínima das chaves precisa ser remapeada para novos servidores. Isso é alcançado através da utilização de um algoritmo de hash que minimiza as mudanças necessárias.

Benefícios do Consistent Hashing:

  • Balanceamento de Carga: Distribui uniformemente as chaves de dados entre os servidores, evitando sobrecarga em servidores individuais.
  • Escalabilidade: Permite adicionar ou remover servidores sem a necessidade de redistribuir todas as chaves, o que simplifica o gerenciamento e a escalabilidade do sistema.
  • Tolerância a Falhas: Se um servidor falha, apenas as chaves mapeadas para esse servidor precisam ser remapeadas para outros servidores, minimizando o impacto da falha.

Exemplo Simplificado de Consistent Hashing:

Vamos criar um exemplo simples de como o Consistent Hashing pode ser implementado em Python:

import hashlib

class ConsistentHashing:
    def __init__(self, nodes):
        self.nodes = nodes
        self.circle = {}
        self._build_circle()

    def _hash(self, key):
        return int(hashlib.md5(key.encode()).hexdigest(), 16)

    def _build_circle(self):
        for node in self.nodes:
            node_hash = self._hash(node)
            self.circle[node_hash] = node

    def get_node(self, key):
        key_hash = self._hash(key)
        sorted_keys = sorted(self.circle.keys())
        for hash_val in sorted_keys:
            if key_hash <= hash_val:
                return self.circle[hash_val]
        return self.circle[sorted_keys[0]]

# Exemplo de uso
nodes = ['Server1', 'Server2', 'Server3']
consistent_hashing = ConsistentHashing(nodes)

# Mapeamento de chaves para servidores
keys = ['Key1', 'Key2', 'Key3', 'Key4']
for key in keys:
    server = consistent_hashing.get_node(key)
    print(f"Chave '{key}' mapeada para o servidor '{server}'")

Explicação do Código:

  • Inicialização: A classe ConsistentHashing é inicializada com uma lista de nós (servidores) disponíveis.
  • Função de Hash: A função _hash usa MD5 para gerar um número hash de 128 bits a partir da chave fornecida.
  • Construção do Círculo: O método _build_circle cria um círculo de hash onde cada nó é mapeado para um ponto no círculo usando o hash da sua identificação (como nome do servidor).
  • Obtenção do Nó: O método get_node recebe uma chave de dados, calcula seu hash e encontra o servidor correspondente usando o círculo de hash. Ele percorre os nós no círculo de hash até encontrar o primeiro nó cujo hash é maior ou igual ao hash da chave.
  • Exemplo de Uso: Cada chave (Key1, Key2, Key3, Key4) é mapeada para um servidor específico (Server1, Server2, Server3) com base no seu hash.

Conclusão

Consistent hashing é uma técnica eficiente e escalável para distribuir dados entre múltiplos servidores em sistemas distribuídos. Ele proporciona um balanceamento de carga eficiente, facilita a escalabilidade e é crucial para manter a disponibilidade e a performance em grandes sistemas distribuídos.

Comentários

Mensagens populares deste blogue

Sistema de Recomendação do Twitter

Sistema de Recomendação do Twitter O sistema de recomendação complexo do Twitter, onde múltiplos componentes trabalham em conjunto para selecionar e classificar os tweets que são exibidos para os usuários na aba "Para você". Vamos descrever cada componente e fase do processo, ilustrando com diagramas e exemplos de código onde aplicável. Fases do Sistema de Recomendação Candidate Sourcing Esta fase é responsável por selecionar os tweets candidatos que podem ser recomendados ao usuário. Os candidatos são coletados de diferentes fontes e algoritmos, como RealGraph, TweepCred, Trust & Safety, GraphJets, etc. Light Ranker (Earlybird) Depois de obter os candidatos, um modelo de machine learning leve (light ranker) faz uma primeira classificação desses tweets. Heavy Ranker Os tweets classificados pelo light ranker são então processados por um modelo mais pesado e complexo (heavy ranker) para uma classificação mais precisa. Heurísticas e Filtros Após o ranqueamento dos tweets, el...

Protocol Buffers (protobuf)

Protocol Buffers (protobuf) O Protocol Buffers (protobuf) é uma alternativa eficiente ao JSON para serialização de dados, especialmente em ambientes de comunicação entre sistemas ou micro-serviços. Aqui estão alguns pontos-chave que explicam por que o protobuf é preferido nesses cenários: Estrutura de Dados Definida No protobuf, você define a estrutura dos dados usando um arquivo .proto , como mostrado no exemplo da mensagem Product e Image . Isso especifica explicitamente cada campo e seu tipo de dados. message Product { string product_id = 1; string name = 2; string description = 3; float price = 4; bool availability = 5; repeated Image images = 6; } message Image { string url = 1; string type = 2; } Compactação de Dados Ao contrário do JSON, que é um formato de texto legível por humanos e verbose, o protobuf gera um formato binário compacto e eficiente. No exemplo mencionado, o mesmo conjunto de dados ocuparia menos de 80 bytes em formato protobuf, comparado a quas...

File Types: Differences

 Tipos de Arquivos: Diferenças As diferenças entre os tipos de arquivos como imagem, texto, áudio, vídeo, e arquivos de redes e mensageria podem ser entendidas considerando como os dados são estruturados, armazenados e processados em termos de bits e bytes. Vamos analisar cada tipo: Imagem Arquivos de imagem são matrizes de pixels, onde cada pixel é representado por um valor de cor. A profundidade de cor (número de bits por pixel) determina a quantidade de cores possíveis. Tipos comuns : JPEG, PNG, BMP, GIF. Estrutura : Matriz bidimensional de pixels. Grayscale (escala de cinza) : Cada pixel é geralmente representado por 8 bits (1 byte). RGB (colorido) : Cada pixel tem 3 componentes (vermelho, verde, azul), cada um representado por 8 bits, totalizando 24 bits (3 bytes) por pixel. PNG com transparência (RGBA) : 4 componentes (vermelho, verde, azul, alfa), totalizando 32 bits (4 bytes) por pixel. Texto Arquivos de texto armazenam caracteres em sequências de bytes. O número de bytes p...