Hashes do Redis (Parte 2)

Esta lição aborda operações numéricas em campos hash, consultas iterativas e outros recursos avançados.

HINCRBY: Incrementar Valores de Campo

Campos hash podem armazenar strings numéricas e suportar operações aritméticas atômicas.

HINCRBY: Incremento de Inteiro

REDIS
# Criar estatísticas de artigo
HSET article:123 views 1000 likes 50 comments 20

# Incrementar contagem de visualizações
HINCRBY article:123 views 1
(integer) 1001

# Incrementar contagem de curtidas
HINCRBY article:123 likes 1
(integer) 51

# Incremento em lote
HINCRBY article:123 views 10
(integer) 1011

# Decrementar (passar um número negativo)
HINCRBY article:123 likes -1
(integer) 50

HINCRBYFLOAT: Incremento de Ponto Flutuante

REDIS
# Preço do produto
HSET product:2001 price 99.99

# Aumentar preço
HINCRBYFLOAT product:2001 price 10.5
"110.49"

# Diminuir preço (passar um número negativo)
HINCRBYFLOAT product:2001 price -5.0
"105.49"

Caso de Uso: Grupo de Contadores

REDIS
# Estatísticas do usuário
HSET user:stats:1 posts 0 followers 0 following 0

# Publicar um artigo
HINCRBY user:stats:1 posts 1

# Ganhar um seguidor
HINCRBY user:stats:1 followers 1

# Seguir alguém
HINCRBY user:stats:1 following 1

# Visualizar estatísticas
HGETALL user:stats:1
💡 Vantagem: Usar um hash para armazenar múltiplos contadores é mais eficiente em memória do que usar múltiplas chaves string.

HSCAN: Iterar por Hashes Grandes

Quando um hash tem muitos campos, HGETALL retorna todos os dados de uma vez, o que pode bloquear o servidor. HSCAN permite iteração em lote.

Uso Básico

REDIS
# Criar um hash grande
HSET grande:hash campo1 "valor1" campo2 "valor2" ... campo1000 "valor1000"

# Iniciar iteração
HSCAN grande:hash 0
1) "127"          # Cursor para a próxima iteração
2) 1) "campo1"
   2) "valor1"
   3) "campo2"
   4) "valor2"
   ...

# Continuar iteração
HSCAN grande:hash 127
1) "0"            # Cursor 0 significa que a iteração está completa
2) 1) "campo999"
   2) "valor999"
   ...

Corresponder Padrão

REDIS
# Obter apenas campos que correspondem a um padrão
HSCAN user:1 0 MATCH age*
1) "0"
2) 1) "age"
   2) "25"

Especificar Contagem por Iteração

REDIS
# Retornar aproximadamente 100 campos por iteração
HSCAN grande:hash 0 COUNT 100
💡 Caso de uso: HSCAN é ótimo para iterar em hashes grandes sem bloquear o servidor.

Aplicações Avançadas de Hash

Caso de Uso 1: Detalhes de Produto de E-commerce

REDIS
# Armazenar informações completas do produto
HSET product:3001 \
  name "iPhone 15 Pro" \
  brand "Apple" \
  price 8999 \
  stock 100 \
  category "phone" \
  sales 0 \
  rating 4.8

# Visualizar informações básicas do produto
HMGET product:3001 name price stock

# Incrementar vendas
HINCRBY product:3001 sales 1

# Decrementar estoque
HINCRBY product:3001 stock -1

# Atualizar avaliação
HSET product:3001 rating 4.9

# Verificar estoque
HGET product:3001 stock

Caso de Uso 2: Configuração do Usuário

REDIS
# Armazenar configuração do usuário
HSET user:config:1 \
  theme "dark" \
  language "pt-br" \
  notifications "on" \
  privacy "public" \
  timezone "America/Sao_Paulo"

# Obter uma única configuração
HGET user:config:1 theme

# Modificar uma configuração
HSET user:config:1 theme "light"

# Obter configurações em lote
HMGET user:config:1 theme language notifications

Caso de Uso 3: Estatísticas em Tempo Real

REDIS
# Estatísticas diárias do site
HSET stats:20260623 \
  page_views 0 \
  unique_visitors 0 \
  new_users 0 \
  orders 0 \
  revenue 0.0

# Incrementar visualizações de página
HINCRBY stats:20260623 page_views 1

# Incrementar visitantes únicos
HINCRBY stats:20260623 unique_visitors 1

# Incrementar pedidos
HINCRBY stats:20260623 orders 1

# Incrementar receita
HINCRBYFLOAT stats:20260623 revenue 299.99

# Visualizar estatísticas
HGETALL stats:20260623

Caso de Uso 4: Configuração de Teste A/B

REDIS
# Armazenar configuração do experimento
HSET experiment:homepage \
  button_color "blue" \
  layout "grid" \
  show_banner "yes" \
  discount_rate 0.1

# Obter configuração do experimento
HGET experiment:homepage button_color

# Atualizar configuração do experimento
HSET experiment:homepage button_color "red"

Hash vs JSON Comparação

Comparação de Armazenamento

Método 1: Hash

REDIS
HSET user:1 name "Alice" age 25 email "alice@example.com"

Método 2: String JSON

REDIS
SET user:1 '{"name":"Alice","age":25,"email":"alice@example.com"}'

Comparação de Operações

Operação Hash String JSON
Obter campo único HGET user:1 name Precisa analisar JSON
Modificar campo único HSET user:1 age 26 Ler → analisar → modificar → serializar → escrever de volta
Obter todos os campos HGETALL user:1 GET user:1 + analisar JSON
Operação numérica HINCRBY user:1 age 1 Precisa analisar → modificar → serializar
Uso de memória Menor Maior (overhead de formato JSON)

Comparação de Casos de Uso

Cenário Recomendado Motivo
Perfil de usuário Hash Campos independentes, atualizações frequentes
Informações de produto Hash Campos independentes, atualizações parciais
Objetos aninhados complexos String JSON Hash não suporta aninhamento
Dados de array String JSON Hash não suporta arrays
Objeto de configuração Hash Campos independentes, consultas rápidas
💡 Princípio de seleção:

  • Campos independentes, atualizações parciais frequentes → Hash
  • Aninhamento complexo, arrays necessários → String JSON
  • Operações numéricas necessárias → Hash

Otimização de Desempenho

1. Evitar Hashes Grandes

REDIS
# ❌ Não recomendado: hash único com muitos campos
HSET grande:hash campo1 ... campo10000

# ✅ Recomendado: fragmentar em múltiplos hashes
HSET hash:parte1 campo1 ... campo1000
HSET hash:parte2 campo1001 ... campo2000

2. Usar HSCAN em Vez de HGETALL

REDIS
# ❌ HGETALL em hash grande
HGETALL grande:hash  # Pode bloquear

# ✅ Usar HSCAN para iteração
HSCAN grande:hash 0

3. Operações em Lote Reduzem Viagens de Rede

REDIS
# ❌ Múltiplas operações individuais
HSET user:1 name "Alice"
HSET user:1 age 25
HSET user:1 city "Beijing"

# ✅ Operação em lote
HSET user:1 name "Alice" age 25 city "Beijing"

4. Configurar Limites de Codificação

Em redis.conf:

CONF
# Limite de contagem de campos hash (padrão 512)
hash-max-ziplist-entries 512

# Tamanho máximo do valor do campo hash (padrão 64 bytes)
hash-max-ziplist-value 64
ℹ️ Observação: Aumentar os limites pode economizar memória, mas pode reduzir o desempenho. Ajuste com base nos seus dados reais.

Limitações do Hash

1. Sem Suporte a Aninhamento

REDIS
# ❌ Não pode armazenar objetos aninhados diretamente
HSET user:1 address '{"city":"Beijing","zip":"100000"}'

# ✅ Usar string para partes aninhadas
HSET user:1 city "Beijing" zip "100000"

2. Sem Suporte a Array

REDIS
# ❌ Não pode armazenar arrays
HSET user:1 tags ["redis","database","cache"]

# ✅ Usar set ou list para arrays
SADD user:1:tags "redis" "database" "cache"

3. Valores Só Podem Ser Strings

REDIS
# Todos os valores são strings
HSET user:1 age 25
HGET user:1 age
"25"  # Retorna string, não inteiro

❓ Perguntas Frequentes

P O que acontece se HINCRBY for usado em um campo não numérico?
R Retorna um erro: (error) ERR hash value is not an integer. Certifique-se de que o valor do campo é uma string numérica.
P Campos hash são ordenados?
R Não. Campos hash não são ordenados — HGETALL não garante nenhuma ordem específica.
P Como verifico se uma chave é do tipo hash?
R Use o comando TYPE: TYPE user:1 retorna hash.
P HSCAN garante que não há duplicatas?
R Não. HSCAN pode retornar campos duplicados — a camada de aplicação precisa tratar a deduplicação.
P Qual é a diferença entre hash e set?
R Um hash armazena pares campo-valor; um set armazena elementos únicos. Hashes são para objetos, sets são para tags e relacionamentos.

📖 Resumo

📝 Atividades

  1. Operações numéricas: Use um hash para armazenar estatísticas de artigo (visualizações, curtidas, comentários) e incremente com HINCRBY
  2. Gerenciamento de produto: Use hash para armazenar informações de produto, pratique visualizar, modificar, incrementar vendas, decrementar estoque
  3. Gerenciamento de configuração: Use hash para configuração de usuário, pratique obter configuração única, obter em lote e modificar configurações
  4. Comparação de desempenho: Compare as etapas para modificar um único campo usando hash vs String JSON

Próxima Lição

Na próxima lição, nós aprenderemos sobre Listas do Redis (Parte 1), abordando operações básicas de lista.

100%