Redis: Listas do Redis (Parte 2)
Esta lição aborda operações avançadas de lista, incluindo consulta, modificação e inserção de elementos.
1. LINDEX: Obter Elemento por Índice
LINDEX recupera um elemento pelo seu índice sem removê-lo.
(1) Uso Básico
LPUSH mylist "um" "dois" "três" "quatro" "cinco"
# Obter o primeiro elemento (índice 0)
LINDEX mylist 0
"cinco"
# Obter o segundo elemento
LINDEX mylist 1
"quatro"
# Obter o último elemento
LINDEX mylist -1
"um"
# Obter o penúltimo elemento
LINDEX mylist -2
"dois"
(2) Índice Fora do Intervalo
# Retorna nil quando o índice está fora do intervalo
LINDEX mylist 10
(nil)
LINDEX mylist -10
(nil)
2. LSET: Definir Elemento por Índice
LSET modifica o elemento em um índice especificado.
(1) Uso Básico
LRANGE mylist 0 -1
1) "cinco"
2) "quatro"
3) "três"
4) "dois"
5) "um"
# Modificar o primeiro elemento
LSET mylist 0 "PRIMEIRO"
OK
# Modificar o último elemento
LSET mylist -1 "ÚLTIMO"
OK
LRANGE mylist 0 -1
1) "PRIMEIRO"
2) "quatro"
3) "três"
4) "dois"
5) "ÚLTIMO"
(2) Índice Fora do Intervalo
LSET mylist 10 "valor"
(error) ERR index out of range
3. LINSERT: Inserir Antes ou Depois de um Elemento de Referência
LINSERT insere um novo elemento antes ou depois de um elemento de referência especificado.
(1) LINSERT BEFORE: Inserir Antes
LRANGE mylist 0 -1
1) "PRIMEIRO"
2) "quatro"
3) "três"
4) "dois"
5) "ÚLTIMO"
# Inserir "ANTES_TRÊS" antes de "três"
LINSERT mylist BEFORE "três" "ANTES_TRÊS"
(integer) 6 # Retorna o tamanho da lista
LRANGE mylist 0 -1
1) "PRIMEIRO"
2) "quatro"
3) "ANTES_TRÊS"
4) "três"
5) "dois"
6) "ÚLTIMO"
(2) LINSERT AFTER: Inserir Depois
# Inserir "DEPOIS_TRÊS" depois de "três"
LINSERT mylist AFTER "três" "DEPOIS_TRÊS"
(integer) 7
LRANGE mylist 0 -1
1) "PRIMEIRO"
2) "quatro"
3) "ANTES_TRÊS"
4) "três"
5) "DEPOIS_TRÊS"
6) "dois"
7) "ÚLTIMO"
(3) Elemento de Referência Não Encontrado
# Elemento de referência especificado não existe
LINSERT mylist BEFORE "naoexiste" "valor"
(integer) -1 # Retorna -1 quando o pivô não é encontrado
4. LREM: Remover Elementos por Valor
LREM remove elementos da lista que correspondem a um valor especificado.
(1) Uso Básico
LPUSH mylist "a" "b" "a" "c" "a" "d"
LRANGE mylist 0 -1
1) "d"
2) "a"
3) "c"
4) "a"
5) "b"
6) "a"
# Remover 2 ocorrências de "a" a partir da cabeça
LREM mylist 2 "a"
(integer) 2 # Deletou 2
LRANGE mylist 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
(2) Referência de Parâmetros
| Parâmetro | Descrição |
|---|---|
| count > 0 | Remover count ocorrências a partir da cabeça |
| count < 0 | Remover abs(count) ocorrências a partir da cauda |
| count = 0 | Remover todos os elementos correspondentes |
(3) Remover da Cauda
LPUSH mylist "a" "b" "a" "c" "a"
# Remover 1 ocorrência de "a" a partir da cauda
LREM mylist -1 "a"
(integer) 1
(4) Remover Todos os Elementos Correspondentes
LPUSH mylist "a" "b" "a" "c" "a"
# Remover todos os "a"
LREM mylist 0 "a"
(integer) 3
LRANGE mylist 0 -1
1) "c"
2) "b"
5. RPOPLPUSH: Mover Elementos
RPOPLPUSH remove o elemento da cauda de uma lista e o insere na cabeça de outra lista.
(1) Uso Básico
# Lista de origem
LPUSH source "um" "dois" "três"
# Lista de destino
LPUSH destination "a" "b"
# Mover cauda da origem para cabeça do destino
RPOPLPUSH source destination
"um" # Retorna o elemento movido
LRANGE source 0 -1
1) "três"
2) "dois"
LRANGE destination 0 -1
1) "um"
2) "a"
3) "b"
(2) Caso de Uso: Fila Circular
# Mover uma tarefa da cauda de volta para a cabeça para processamento round-robin
RPOPLPUSH queue:task queue:task
(3) Caso de Uso: Fila de Backup
# Mover tarefa para fila de backup durante o processamento
RPOPLPUSH queue:task queue:backup
# Se o processamento falhar, a tarefa pode ser recuperada da fila de backup
6. BRPOPLPUSH: Movimento Bloqueante
BRPOPLPUSH é a versão bloqueante de RPOPLPUSH.
# Se a lista de origem estiver vazia, aguardar bloqueante por até 10 segundos
BRPOPLPUSH source destination 10
7. LMOVE: Mover Elementos (Redis 6.2+)
LMOVE é uma versão generalizada de RPOPLPUSH que permite especificar ambas as posições de origem e destino.
# Remover da direita da origem, inserir à esquerda do destino
LMOVE source destination RIGHT LEFT
# Remover da esquerda da origem, inserir à direita do destino
LMOVE source destination LEFT RIGHT
8. Aplicações Avançadas de Lista
(1) Caso de Uso 1: Paginação
# Lista de artigos
LPUSH articles "article:1" "article:2" ... "article:100"
# Página 1 (10 itens por página)
LRANGE articles 0 9
# Página 2
LRANGE articles 10 19
# Página 3
LRANGE articles 20 29
(2) Caso de Uso 2: Contatos Recentes
# Adicionar um contato à lista recente
LPUSH contacts:user:1 "user:2"
# Se já existir, remover primeiro e depois adicionar (mover para o início)
LREM contacts:user:1 0 "user:2"
LPUSH contacts:user:1 "user:2"
# Obter 10 contatos recentes
LRANGE contacts:user:1 0 9
(3) Caso de Uso 3: Escalonamento Round-Robin
# Lista de tarefas
LPUSH tasks "task1" "task2" "task3"
# Round-robin: remover tarefa, processá-la, depois colocá-la de volta na cauda
RPOPLPUSH tasks tasks
"task1" # Processar task1
# Próxima consulta obterá task2
(4) Caso de Uso 4: Log Limitado
# Adicionar uma entrada de log
LPUSH log:app "mensagem de log"
# Manter as 1000 entradas de log mais recentes
LTRIM log:app 0 999
# Visualizar logs recentes
LRANGE log:app 0 99
9. Otimização de Desempenho de Lista
(1) Evitar Operações no Meio
# ❌ Desempenho ruim: inserir ou deletar no meio
LINSERT mylist BEFORE "meio" "novo"
LREM mylist 1 "meio"
# ✅ Bom desempenho: operar apenas na cabeça e cauda
LPUSH mylist "novo"
LPOP mylist
(2) Evitar Listas Grandes
# ❌ Lista muito grande
LLEN mylist
(integer) 1000000
# ✅ Usar LTRIM para limitar o tamanho
LTRIM mylist 0 9999
(3) Buscar em Lotes com LRANGE
# ❌ Buscar um intervalo enorme de uma vez
LRANGE mylist 0 -1
# ✅ Buscar em lotes
LRANGE mylist 0 99
LRANGE mylist 100 199
(4) Escolher a Estrutura de Dados Correta
| Requisito | Estrutura de Dados Recomendada |
|---|---|
| Fila/Pilha | List |
| Últimos N itens | List + LTRIM |
| Paginação | List + LRANGE |
| Lista deduplicada | Set ou Sorted Set |
| Ordenação ponderada | Sorted Set |
10. Limitações da Lista
(1) Busca Lenta de Elementos
# Encontrar um valor específico requer percorrer a lista inteira
LINDEX mylist 500000 # Operação O(N), muito lenta
(2) Operações Lentas no Meio
# Inserir ou deletar no meio requer deslocar elementos
LINSERT mylist BEFORE "meio" "novo" # O(N)
(3) Não Pode Encontrar Índice por Valor
Redis não fornece um comando para encontrar o índice de um valor pelo seu conteúdo. Isso deve ser implementado no nível da aplicação.
▶ Exemplo
Operações avançadas de lista:
127.0.0.1:6379> RPUSH queue "job1" "job2" "job3"
(integer) 3
127.0.0.1:6379> LLEN queue
(integer) 3
127.0.0.1:6379> LINSERT queue BEFORE "job2" "job1.5"
(integer) 4
127.0.0.1:6379> LRANGE queue 0 -1
1) "job1"
2) "job1.5"
3) "job2"
4) "job3"
❓ Perguntas Frequentes
LINDEX mylist 0 é equivalente a LRANGE mylist 0 0.📖 Resumo
- LINDEX obtém elemento por índice, LSET define elemento por índice
- LINSERT insere antes ou depois de um pivô (desempenho O(N))
- LREM remove elementos por valor, com controle sobre contagem e direção
- RPOPLPUSH move elementos, usado para filas circulares e filas de backup
- BRPOPLPUSH movimento bloqueante, usado para filas de mensagens confiáveis
- Aplicações avançadas de lista: paginação, contatos recentes, escalonamento round-robin
- Otimização de desempenho: evite operações no meio, limite o tamanho da lista, busque em lotes
11. 📝 Atividades
- Operações de índice: Crie uma lista, use LINDEX para obter elementos em diferentes posições, use LSET para modificar elementos
- Inserir e deletar: Use LINSERT para inserir no meio, use LREM para remover elementos por valor
- Movimento de elementos: Use RPOPLPUSH para implementar uma fila circular para round-robin de tarefas
- Paginação: Crie uma lista com 20 elementos e implemente paginação com 5 itens por página
12. Próxima Lição
Na próxima lição, nós aprenderemos sobre Conjuntos do Redis (Parte 1), abordando operações básicas de conjunto.
📝 Exercícios
- Prática: Execute os comandos apresentados nesta lição
- Experimentação: Teste variações dos comandos aprendidos
- Aplicação: Aplique os conceitos em um projeto prático