Structure type | What it contains | Structure read/write ability |
---|---|---|
STRING |
Strings, integers, or floating point values | Operate on the whole string, parts, increment/decrement the integers and floats. |
LIST |
Linked list of strings | Push or pop items from both ends, trim based on offsets, read individual or multiple items, find or remove items by value. |
SET |
Unordered collection of unique strings | Add, fetch, or remove individual items, check membership, intersect, union, difference, fetch random items. |
HASH |
Unordered hash table of keys to values | Add, fetch, or remove individual items, fetch the whole hash. |
ZSET (sorted set) |
Ordered mapping of string members to floating-point scores, ordered by score | Add, fetch, or remove individual values, fetch items based on score ranges or member value. |
STRINGs
No Redis, STRING
s são usadas para armazenar três tipos de valores:
- Byte string values
- Integer values
- Floating-point values
Strings são os tipos de dados mais versáteis no Redis porque têm muitos comandos e múltiplos propósitos. Uma String pode se comportar como um valor inteiro, float, string de texto ou bitmap com base em seu valor e nos comandos usados. Ele pode armazenar qualquer tipo de dados: texto (XML, JSON, HTML ou raw text), inteiros, flutuantes ou dados binários (vídeos, imagens ou arquivos de áudio). Um valor String não pode exceder 512 MB de texto ou dados binários.
Os tipos de string são os tipos de dados básicos no Redis. Embora na terminologia do Redis, string pode ser considerada uma matriz de bytes que pode conter strings, inteiros, imagens, arquivos e objetos serializáveis. Essas matrizes de bytes são binary safe por natureza e o tamanho máximo que podem conter é 512 MB.
Comandos usados na manipulação de strings
-
SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
: Armazena uma chave com seu respectivo valor. Caso já exista uma chave definida, seu valor é sobrescrito;Definindo uma chave com tempo de expiração em segundos -
EX
:redis> DEL mykey redis> SET mykey "Hello" EX 10 # OK # After 5 Seconds redis> TTL mykey # (integer) 5 # Wait 10 Seconds redis> GET mykey # (nil) redis> TTL mykey # (integer) -2 (Key is expired or does not exist)
Atualizando apenas o valor da chave e mantendo seu tempo de expiração -
KEEPTTL
:redis> DEL mykey redis> SET mykey "Will expire in a minute" EX 60 # OK redis> GET mykey # "Will expire in a minute" redis> TTL mykey # (integer) 50 redis> SET mykey "Other value" KEEPTTL # OK redis> TTL mykey # (integer) 30 redis> GET mykey # "Other value" # After 1 minute redis> GET mykey # (nil) redis> TTL mykey # (integer) -2
Atualizando o valor da chave apenas se a mesma não existir -
NX
:redis> DEL mykey redis> SET mykey "Hello" # OK redis> GET mykey # "Hello" redis> TTL mykey # (integer) -1 (Key exists but has no expiration time set) redis> SET mykey "Other value" NX # (nil) redis> GET mykey # "Hello"
Atualizando o valor da chave quando a mesma existir -
XX
:redis> DEL mykey redis> SET mykey "Hello" # OK redis> GET mykey # "Hello" redis> SET mykey "Other value" XX # OK redis> GET mykey # "Other value"
Atualizando o valor da chave e retornando seu valor anterior a atualização -
GET
:redis> DEL mykey redis> SET mykey "Hello" # OK redis> GET mykey # "Hello" redis> SET mykey "Other value" GET # "Hello" redis> GET mykey # "Other value"
-
GET key
: Retorna o valor correspondente à chave informada; -
GETDEL key
: Retorna o valor da chave antes de excluí-la. Este comando é semelhante aoGET
, exceto pelo fato de que após recuperar o valor da chave, a mesma é excluída;redis> DEL mykey redis> SET mykey "Hello" # OK redis> GETDEL mykey # "Hello" redis> GET mykey # (nil)
-
GETEX key [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|PERSIST]
: Recupera o valor da chave e, opcionalmente, você pode definir um tempo de expiração.GETEX
é semelhante aoGET
, com opção adicional de expiração da chave;redis> DEL mykey redis> SET mykey "Hello" # OK redis> GETEX mykey # "Hello" redis> TTL mykey # (integer) -1 redis> GETEX mykey EX 60 # "Hello" redis> TTL mykey # (integer) 50 redis> GETEX mykey PERSIST # "Hello" redis> TTL mykey # (integer) -1
-
APPEND key value
: Concatena um novo valor ao valor atual de uma chave e altera o valor atual da chave;redis> EXISTS mykey # (integer) 0 redis> APPEND mykey "Hello" # (integer) 5 redis> APPEND mykey " World" # (integer) 11 redis> GET mykey # "Hello World"
-
MGET key [key...]
: Retorna os valores correspondentes às chaves informadas;redis> SET key1 "Hello" # OK redis> SET key2 "World" # OK redis> MGET key1 key2 nonexisting # 1) "Hello" # 2) "World" # 3) (nil)
-
INCR key
: Incrementa (adiciona 1) ao valor (número inteiro) da chave; -
INCRBY key increment
: Incrementa ou decrementa o valor (número inteiro) da chave conforme o valor do incremento; -
INCRBYFLOAT key increment
: Incrementa ou decrementa o valor (número de ponto flutuante) da chave conforme o valor do argumentoincrement
; -
DECR key
: Decrementa (remove 1) ao valor (número inteiro) da chave; -
SETNX key value
: Define um valor em relação a chave se a mesma não existir. Nesse caso, é igual aSET
. Quando a chave já contém um valor, nenhuma operação é executada.SETNX
é a abreviação de "SET if Not eXists";redis> SETNX mykey "Hello" # (integer) 1 redis> SETNX mykey "World" # (integer) 0 redis> GET mykey # "Hello"
-
GETSET key value
: Obtém o valor antigo e define um novo valor. Define um novo valor para um chave já existente e retorna o seu valor anterior (antes de ser redefinido pelo comando);redis> DEL mykey # (integer) 1 redis> SET mykey "Hello" # OK redis> GETSET mykey "World" # "Hello" redis> GET mykey # "World"
-
MSET key value [key value ...]
: Armazena um ou mais conjuntos de chave valor. Caso uma chave informada já exista, seu valor será sobrescrito pelo novo;redis> MSET first "First Key value" second "Second Key value" # OK redis> MGET first second # 1) "First Key value" # 2) "Second Key value"
-
MSETNX key value [key value ...]
: Define todos os valores correspondentes das chaves se todas as chaves não existirem, ou seja, se houver uma única chave já existe, nenhuma operação será executada, nenhuma chave será definada.MSETNX
é atômico, então todas as chaves fornecidas são definidas de uma vez. Não é possível para os clientes ver que algumas das chaves foram atualizadas enquanto outras permanecem inalteradas;redis> MSETNX key1 "Hello" key2 "there" # (integer) 1 redis> MSETNX key2 "new" key3 "world" # (integer) 0 redis> MGET key1 key2 key3 # 1) "Hello" # 2) "there" # 3) (nil)
LISTs
LISTs no Redis armazenam uma sequência ordenada de strings.
As listas no Redis são um tipo de estrutura muito flexível, porque podem agir como uma simples collection, stack ou fila. O número máximo de elementos que uma lista pode conter é (2^32 - 1), o que significa que pode haver mais de 4 bilhões de elementos por lista.
A vantagem da lista no Redis de ser implementada como uma lista vinculada em vez de array é porque foi projetada para ter gravações mais rápidas do que leituras.
Os comandos no Redis para as listas normalmente começam com a letra L
. Isso também pode ser interpretado que todos os comandos serão executados da esquerda ou do topo da lista, e onde os comandos são executados da direita ou do final da lista, eles começam com a letra R
. Os comandos podem ser categorizados nas seguintes partes:
-
Setters e Getters:
-
LPUSH key element [element ...]
: Adiciona um ou mais valores ao início/topo (head - esquerda) da lista definida pela chave. Se a chave não existir, ela será criada como uma lista vazia antes de realizar a operação push. Quando a chave contém um valor que não é uma lista, um erro é retornado;redis> DEL books redis> LPUSH books "Clean Code" # (integer) 1 redis> LPUSH books "Clean Architecture" # (integer) 2 redis> LPUSH books "Refactoring" # (integer) 3 redis> LRANGE books 0 -1 # 1) "Refactoring" # 2) "Clean Architecture" # 3) "Clean Code"
-
RPUSH key element [element ...]
: Adiciona um ou mais valores ao final (tail - direita) da lista definida pela chave. Se a chave não existir, ela será criada como uma lista vazia antes de realizar a operação push. Quando a chave contém um valor que não é uma lista, um erro é retornado;redis> DEL books redis> RPUSH books "Clean Code" # (integer) 1 redis> RPUSH books "Clean Architecture" # (integer) 2 redis> RPUSH books "Refactoring" # (integer) 3 redis> LRANGE books 0 -1 # 1) "Clean Code" # 2) "Clean Architecture" # 3) "Refactoring"
-
LPUSHX key element [element ...]
: Funciona da mesma forma que o comandoLPUSH
; a única diferença entre os dois é que o comandoLPUSHX
insere um novo item somente se a chave existir e for uma lista. Ao contrário doLPUSH
, nenhuma operação será realizada quando a chave não existir;redis> DEL books redis> LPUSH books "Clean Code" # (integer) 1 redis> LPUSH books "Clean Architecture" # (integer) 2 redis> LPUSHX nonexisting "Hello" # (integer) 0 redis> LRANGE books 0 -1 # 1) "Clean Architecture" # 2) "Clean Code" redis> LRANGE nonexisting 0 -1 # (empty array)
-
RPUSHX key element [element ...]
: Funciona da mesma forma que o comandoRPUSH
; a única diferença entre os dois é que o comandoRPUSHX
insere um novo item somente se a chave existir e for uma lista. Ao contrário doRPUSH
, nenhuma operação será realizada quando a chave não existir; -
LINSERT key BEFORE|AFTER pivot element
: Insere um elemento na lista antes ou depois da posição do pivot do valor de referência. Quando a chave não existe, é considerada uma lista vazia e nenhuma operação é realizada;redis> DEL mylist redis> RPUSH mylist "Hello" # (integer) 1 redis> RPUSH mylist "World" # (integer) 2 redis> LINSERT mylist BEFORE "World" "value 3" # (integer) 3 redis> LRANGE mylist 0 -1 # 1) "Hello" # 2) "value 3" # 3) "World" redis> LINSERT mylist AFTER "World" "value 4" # (integer) 4 # 1) "Hello" # 2) "value 3" # 3) "World" # 4) "value 4"
-
LSET key index element
: Define o valor de um elemento com base no índice especificado; -
LRANGE key start stop
: Obtém a sub-lista de elementos com base no índice inicial e no índice final. Os offsetsstart
estop
são índices baseados em zero, com0
sendo o primeiro elemento da lista (o topo da lista),1
sendo o próximo elemento e assim por diante. Esses offsets também podem ser números negativos, indicando offsets que começam no final da lista. Por exemplo,-1
é o último elemento da lista,-2
é o penúltimo e assim por diante;
-
-
Data Clean:
-
LTRIM key start stop
: Excluí os elementos fora do intervalo especificado. Apara a lista deixando apenas os itens definidos entre os índices destart
estop
;redis> DEL mylist redis> RPUSH mylist "one" # (integer) 1 redis> RPUSH mylist "two" # (integer) 2 redis> RPUSH mylist "three" # (integer) 3 redis> LTRIM mylist 1 -1 # OK redis> LRANGE mylist 0 -1 # 1) "two" # 2) "three"
-
RPOP key [count]
: Remove e retorna os últimos (tail) elementos da lista ou (nil) caso a lista esteja vazia. Por padrão, o comando remove um único elemento do final da lista. Quando fornecido com o argumento opcional de[count]
, removerá a quantidade de elementos definido no argumento[count]
;redis> DEL mylist redis> RPUSH mylist "one" "two" "three" "four" "five" # (integer) 5 redis> RPOP mylist # "five" redis> RPOP mylist 2 # 1) "four" # 2) "three" redis> LRANGE mylist 0 -1 # 1) "one" # 2) "two"
-
LREM key count element
: Remove a quantidade de elementos de acordo com o argumentocount
, começando no índice espeficicado pelo argumentoelement
; -
LPOP key [count]
: Remove e retorna os primeiros (head) elementos da lista ou (nil) caso a lista esteja vazia. Por padrão, o comando remove um único elemento do início da lista. Quando fornecido com o argumento opcional de[count]
, removerá a quantidade de elementos definido no argumento[count]
;redis> DEL mylist redis> RPUSH mylist "one" "two" "three" "four" "five" # (integer) 5 redis> LPOP mylist # "one" redis> LPOP mylist 2 # 1) "two" # 2) "three" redis> LRANGE mylist 0 -1 # 1) "four" # 2) "five"
-
-
Utility:
-
LINDEX key index
: Retorna o valor de um item da lista de acordo com o índice informado. O índice é baseado em zero, então0
significa o primeiro elemento,1
o segundo elemento e assim por diante. Índices negativos podem ser usados para designar elementos começando no final da lista.-1
significa o último elemento,-2
significa o penúltimo e assim por diante;redis> DEL mylist redis> LPUSH mylist "one" "two" "three" # (integer) 3 redis> LINDEX mylist 0 # "three" redis> LINDEX mylist 1 # "two" redis> LINDEX mylist 2 # "one" redis> LINDEX mylist 3 # (nil) redis> LINDEX mylist -1 # "one" redis> LINDEX mylist -2 # "two" redis> LINDEX mylist -3 # "three" # LLEN redis> LLEN mylist # (integer) 3
-
LLEN key
: Retorna a quantidade de itens armazenados em uma lista. Se a chave não existir, ela será interpretada como uma lista vazia e0
será retornado;
-
-
Advanced:
-
BLPOP key [key ...] timeout
: Bloqueia a conexão para remover e retornar o primeiro item de uma das listas informadas como parâmetro durante um tempo máximo definido no parâmetrotimeout
. Casotimeout
seja definido como0
, a conexão fica bloqueada até que um item de uma das listas informadas seja removido e retornado pelo comando; -
BRPOP key [key ...] timeout
: Bloqueia a conexão para remover e retornar o último item de uma das listas informadas como parâmetro durante um tempo máximo definido no parâmetrotimeout
. Casotimeout
seja definido como0
, a conexão fica bloqueada até que um item de uma das listas informadas seja removido e retornado pelo comando; -
RPOPLPUSH source destination
: Opera em duas listas. Retorna e remove atomicamente o último elemento (tail) da lista do argumento desource
e o envia para a lista do argumentodestination
na posição de primeiro elemento (head); -
BRPOPLPUSH source destination timeout
:BRPOPLPUSH
é a variante de bloqueio deRPOPLPUSH
. Nesse caso, se a lista do argumentosource
estiver vazia, o Redis bloqueará a operação/conexão até que um valor seja adicionado ou até que o tempo limite do argumentotimeout
seja atingido. Um tempo limite de zero pode ser usado para bloquear indefinidamente;
-
SETs
Um Set no Redis são estruturas de dados que são uma coleção/conjunto não ordenada de strings distintas - não é possível adicionar elementos repetidos/duplicados a um Set. Internamente, um Set é implementado como uma tabela hash, razão pela qual algumas operações são otimizadas: adição de membros, remoção e execução de pesquisa em
O(1)
, tempo constante. Um dos aspectos interessantes em termos de desempenho dos Sets é que eles mostram um tempo constante para adicionar, remover e verificar a existência de um elemento.
O número máximo de elementos que um Set pode conter é (2^32 - 1), o que significa que pode haver mais de 4 bilhões de elementos por Set.
Os comandos no Redis para os Sets podem ser categorizados nas seguintes partes:
-
Setters e Getters:
-
SADD key member [member ...]
: Adicione os membros especificados ao conjunto definido pela chave. Membros especificados que já são membros deste conjunto são ignorados. Se a chave não existir, um novo conjunto será criado antes de adicionar os membros especificados;redis> DEL myset redis> SADD myset "Hello" # (integer) 1 redis> SADD myset "World" # (integer) 1 redis> SADD myset "World" # (integer) 0 redis> SCARD myset # (integer) 2 redis> SMEMBERS myset # 1) "World" # 2) "Hello"
-
-
Data Clean:
-
SPOP key [count]
: Remove e retorna um ou mais membros aleatórios do conjunto definido pela chave; -
SREM key member [member ...]
: Remova os membros especificados do conjunto definido pela chave. Membros especificados que não são membros deste conjunto são ignorados. Se a chave não existir, ela será tratada como um conjunto vazio e este comando retornará0
;redis> DEL myset redis> SADD myset "one" "two" "three" # (integer) 3 redis> SREM myset "one" "three" # (integer) 2 redis> SREM myset "four" # (integer) 0 redis> SMEMBERS myset # 1) "two"
-
-
Utility:
-
SCARD key
: Retorna a quantidade de itens armazenados em um conjunto; -
SDIFF key [key ...]
: Retorna os membros do conjunto resultantes da diferença entre o primeiro conjunto e todos os conjuntos sucessivos; -
SDIFFSTORE destination key [key ...]
: Este comando é igual aSDIFF
, mas em vez de retornar o conjunto resultante, ele é armazenado na chave de conjunto do argumentodestination
. Se a chavedestination
já existir, ela será sobrescrito;redis> DEL key key1 key2 redis> SADD key1 "a" "b" "c" # (integer) 3 redis> SADD key2 "c" "d" "e" # (integer) 3 redis> SDIFF key1 key2 # 1) "a" # 2) "b" redis> SDIFF key2 key1 # 1) "d" # 2) "e" redis> SDIFFSTORE key key1 key2 # (integer) 2 redis> SMEMBERS key # 1) "a" # 2) "b"
-
SINTER key [key ...]
: Retorna os elementos resultantes entre uma intersecção dos conjuntos informados; -
SINTERSTORE destination key [key ...]
: Este comando é igual aoSINTER
, mas em vez de retornar o conjunto resultante, ele é armazenado na chave de conjunto do argumentodestination
. Se a chavedestination
já existir, ela será sobrescrito;redis> DEL key key1 key2 redis> SADD key1 "a" "b" "c" # (integer) 3 redis> SADD key2 "c" "d" "e" # (integer) 3 redis> SINTER key1 key2 # 1) "c" redis> SINTERSTORE key key1 key2 # (integer) 1 redis> SMEMBERS key # 1) "c"
-
SISMEMBER key member
: Retorna1
se o valor informado existe no conjunto informado pela chave, caso o valor não exista o comando retorna o valor0
;redis> DEL myset redis> SADD myset "one" # (integer) 1 redis> SISMEMBER myset "one" # (integer) 1 redis> SISMEMBER myset "two" # (integer) 0
-
SMISMEMBER key member [member ...]
: Retorna1
se cada membro do argumento demember
é um membro/está no conjunto da chave informada. Para cada membro,1
é retornado se o valor for um membro do conjunto, ou0
se o elemento não for um membro do conjunto ou se a chave não existir;redis> DEL myset redis> SADD myset "a" "b" "c" "d" "e" "f" # (integer) 6 redis> SMISMEMBER myset "a" "d" "f" "notamember" # 1) (integer) 1 # 2) (integer) 1 # 3) (integer) 1 # 4) (integer) 0
-
SMEMBERS key
: Retorna todos os elementos de um conjunto definido pela chave informada; -
SMOVE source destination member
: Mova o membro do argumentomember
do conjunto do argumentosource
para o conjunto do argumentodestination
; -
SUNION key [key ...]
: Retorna os membros do conjunto resultantes da união de todos os conjuntos fornecidos; -
SUNIONSTORE destination key [key ...]
: Este comando é igual aSUNION
, mas em vez de retornar o conjunto resultante, ele é armazenado na chave de conjunto do argumentodestination
. Se a chavedestination
já existir, ela será sobrescrito;redis> DEL key key1 key2 redis> SADD key1 "a" "b" "c" # (integer) 3 redis> SADD key2 "c" "d" "e" # (integer) 3 redis> SUNION key1 key2 # 1) "a" # 2) "b" # 3) "d" # 4) "c" # 5) "e" redis> SUNIONSTORE key key1 key2 # (integer) 5 redis> SMEMBERS key # 1) "a" # 2) "b" # 3) "d" # 4) "c" # 5) "e"
-
Sorted Sets
Como os tipos de
HASH
, osZSET
s também contêm um tipo de chave e valor. As chaves (chamadas de members) são únicas/exclusivas e os valores (chamados de scores) são limitados a números de ponto flutuante.ZSET
s têm a propriedade única no Redis de poder ser acessado por um membro (como umHASH
), mas os itens também podem ser acessados pela ordem de classificação e pelos valores das pontuações.
Um Sorted Set é muito semelhante a um Set, mas cada elemento de um Sorted Set tem uma pontuação associada. Em outras palavras, um Sorted Set é uma coleção de strings não repetidas classificadas por uma pontuação. É possível ter elementos com pontuações repetidas. Nesse caso, os elementos repetidos são ordenados lexicograficamente (em ordem alfabética).
As operações em Sorted Set são rápidas, mas não tão rápidas quanto as operações em Set, porque as pontuações precisam ser comparadas. Adicionar, remover e atualizar um item em um Sorted Set é executado em tempo logarítmico, O(log(N))
, onde N
é o número de elementos em um Sorted Set. Internamente, os Sorted Sets são implementados como duas estruturas de dados separadas:
- Uma skip list com uma tabela hash. Uma skip list é uma estrutura de dados que permite uma pesquisa rápida em uma sequência ordenada de elementos.
- Um
ziplist
, com base nas configuraçõeszset-max-ziplist-entries
ezset-max-ziplist-value
.
Os Sorted Sets são muito parecidos com os Sets do Redis, pois não armazenam valores duplicados, mas a área em que eles diferem dos Sets é que os valores são classificados com base em uma pontuação, ou inteiros, valores flutuantes. Esses valores são fornecidos ao definir um valor no Conjunto. O desempenho desses Sorted Sets é proporcional ao logaritmo do número de elementos. Os dados são sempre mantidos de forma ordenada. Esse conceito é explicado na imagem abaixo:
Os comandos no Redis para os Sorted Sets podem ser categorizados nas seguintes partes:
-
Setters e Getters:
-
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
: Adiciona todos os membros com seus scores/pontuações de uma determinada chave. Se um membro especificado já for membro do conjunto, a pontuação/score é atualizada e o elemento reinserido para garantir a ordem correta;Definindo as chaves:
redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "1" # 3) "two" # 4) "2" # 5) "three" # 6) "3"
Atualizando apenas os elementos que já existem -
XX
:redis> ZADD myzset XX 10 "one" 20 "notamember" # (integer) 0 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "two" # 2) "2" # 3) "three" # 4) "3" # 5) "one" # 6) "10"
Adicionar novos elementos. Não atualizar elementos existentes -
NX
:redis> ZADD myzset NX 20 "one" 30 "thirty" # (integer) 1 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "two" # 2) "2" # 3) "three" # 4) "3" # 5) "one" # 6) "10" # 7) "thirty" # 8) "30"
Atualizar os elementos se a nova pontuação for MENOR que a pontuação atual. Essa flag não impede a adição de novos elementos -
LT
:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZADD myzset LT 2 "three" 3 "for" 30 "thirty" # (integer) 1 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "1" # 3) "three" # 4) "2" # 5) "two" # 6) "2" # 7) "for" # 8) "3" # 9) "five" # 10) "5" # 11) "thirty" # 12) "30"
Atualizar os elementos se a nova pontuação for MAIOR que a pontuação atual. Essa flag não impede a adição de novos elementos -
GT
:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "1" # 3) "two" # 4) "2" # 5) "three" # 6) "3" # 7) "for" # 8) "4" # 9) "five" # 10) "5" redis> ZADD myzset GT 2 "one" 3 "two" 4 "three" # (integer) 0 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "2" # 3) "two" # 4) "3" # 5) "for" # 6) "4" # 7) "three" # 8) "4" # 9) "five" # 10) "5"
-
ZRANGE key min max [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
: Retorna uma quantidade (range) de elementos. Os elementos são ordenados do menor score para o maior, e o range de elementos é definido conforme os valores dos argumentosmin
emax
(pelo índice/rank, score ou lexicográfia). O argumento opcionalWITHSCORES
, quando informado, faz com que o comando além de retornar os elementos também retorne os scores de cada elemento;<min>
e<max>
podem ser-inf
e+inf
, denotando os infinitos negativo e positivo, respectivamente. Isso significa que você não precisa saber a pontuação mais alta ou mais baixa no conjunto para obter todos os elementos de ou até uma determinada pontuação.Por padrão, os intervalos de pontuação especificados por
<min>
e<max>
são fechados (inclusivos). É possível especificar um intervalo aberto (exclusivo) prefixando o score com o caractere(
.Retornando todos os elementos juntamente com seus scores/pontuações -
WITHSCORES
:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "1" # 3) "two" # 4) "2" # 5) "three" # 6) "3" # 7) "for" # 8) "4" # 9) "five" # 10) "5"
Retornando todos os elementos na ordem reversa -
REV
:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZRANGE myzset 0 -1 REV WITHSCORES # 1) "five" # 2) "5" # 3) "for" # 4) "4" # 5) "three" # 6) "3" # 7) "two" # 8) "2" # 9) "one" # 10) "1" redis> ZRANGE myzset 0 2 REV WITHSCORES # 1) "five" # 2) "5" # 3) "for" # 4) "4" # 5) "three" # 6) "3"
Recuperar os elementos de acordo com o score -
BYSCORE
:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZRANGE myzset 0 1 BYSCORE WITHSCORES # 1) "one" # 2) "1" redis> ZRANGE myzset 2 4 BYSCORE WITHSCORES # 1) "two" # 2) "2" # 3) "three" # 4) "3" # 5) "for" # 6) "4"
Limitando a quantidade de elementos retornados (funciona apenas junto com a opção
BYSCORE
ouBYLEX
) -LIMIT
:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZRANGE myzset 0 5 BYSCORE LIMIT 0 1 WITHSCORES # 1) "one" # 2) "1" redis> ZRANGE myzset 0 5 BYSCORE LIMIT 1 1 WITHSCORES # 1) "two" # 2) "2" redis> ZRANGE myzset 0 5 BYSCORE LIMIT 0 2 WITHSCORES # 1) "one" # 2) "1" # 3) "two" # 4) "2" redis> ZRANGE myzset 0 5 BYSCORE LIMIT 1 2 WITHSCORES # 1) "two" # 2) "2" # 3) "three" # 4) "3"
Usando o caractere
(
(apenas com a opçãoBYSCORE
) para excluir (exclusivo) os elementos por meio de seus scores:redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "for" 5 "five" # (integer) 5 redis> ZRANGE myzset (1 +inf BYSCORE WITHSCORES # 1) "two" # 2) "2" # 3) "three" # 4) "3" # 5) "for" # 6) "4" # 7) "five" # 8) "5" redis> ZRANGE myzset (2 +inf BYSCORE LIMIT 1 2 WITHSCORES # 1) "for" # 2) "4" # 3) "five" # 4) "5"
-
ZREVRANGE key start stop [WITHSCORES]
: Funciona da mesma forma que o comandoZRANGE
, porém faz a ordenação de elementos levando em consideração o maior score para o menor (decrescente); -
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
: Retorna todos os elementos de uma determinada chave do intervalo por pontuação fornecida. Tendo o score/pontuação entre os valores dos argumentosmin
emax
(incluindo elementos com score/pontuação igual amin
oumax
). Os elementos são considerados ordenados do menor para a maior pontuação (ordem crescente); -
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
: Retorna todos os elementos na chave de sorted set com uma pontuação entremax
emin
(incluindo elementos com pontuação igual amax
oumin
). Ao contrário da ordem padrão dos sorted sets, para este comando os elementos são considerados ordenados dos maiores para as menores pontuações (decrescente); -
ZREVRANK key member
: Retorna a classificação do membro na chave de sorted set, com as pontuações ordenadas de forma decrescente. A classificação (ou índice) é baseada em0
, o que significa que o membro com a pontuação mais alta tem classificação0
;
-
-
Data Clean:
-
ZREM key member [member ...]
: Remove os membros especificados. Membros não existentes são ignorados;redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZREM myzset "two" # (integer) 1 redis> ZREM myzset "five" # (integer) 0 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "1" # 3) "three" # 4) "3"
-
ZREMRANGEBYRANK key start stop
: Remove todos os elementos do conjunto com classificação entre os argumentos destart
estop
. Tanto os argumentos destart
quantostop
são índices iniciados em0
, sendo0
o elemento com a pontuação mais baixa. Esses índices podem ser números negativos, onde indicam offsets começando no elemento com a pontuação mais alta. Por exemplo:-1
é o elemento com a pontuação mais alta,-2
o elemento com a segunda pontuação mais alta e assim por diante;redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZREMRANGEBYRANK myzset 1 2 # (integer) 2 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "one" # 2) "1"
-
ZREMRANGEBYSCORE key min max
: Remove todos os elementos do conjunto com uma pontuação/score entre os argumentos demin
emax
(inclusive);redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZREMRANGEBYSCORE myzset -inf (2 # (integer) 1 redis> ZRANGE myzset 0 -1 WITHSCORES # 1) "two" # 2) "2" # 3) "three" # 4) "3"
-
-
Utility:
-
ZCARD key
: Retorna a quantidade de elementos armazenados em um sorted Set; -
ZCOUNT key min max
: Retorna o número de membros em um sorted set que possui o score entre um valor do argumento demin
emax
;redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZCOUNT myzset -inf +inf # (integer) 3 redis> ZCOUNT myzset 2 +inf # (integer) 2 redis> ZCOUNT myzset (2 +inf # (integer) 1 redis> ZCOUNT myzset -inf (3 # (integer) 2 redis> ZCOUNT myzset -inf (2 # (integer) 1 redis> ZCOUNT myzset (1 3 # (integer) 2
-
ZINCRBY key increment member
: Incrementa o score de um membro do sorted set definido pela chave informada como argumento; -
ZRANK key member
: Retorna a classificação/índice dos membros de um Sorted Set, realizando a ordenação do menor score para o maior;redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZRANK myzset "one" # (integer) 0 redis> ZRANK myzset "two" # (integer) 1 redis> ZRANK myzset "three" # (integer) 2 redis> ZRANK myzset "four" # (nil)
-
ZSCORE key member
: Retorna o score de um membro de um sorted set;redis> DEL myzset redis> ZADD myzset 1 "one" 2 "two" 3 "three" # (integer) 3 redis> ZSCORE myzset "one" # "1" redis> ZSCORE myzset "three" # "3"
-
Hashes
Enquanto
LIST
eSET
no Redis contêm uma sequências de elementos, osHASH
es no Redis armazenam um mapeamento de chave-valor. Os valores que podem ser armazenados emHASH
são os mesmos que podem ser armazenados comoSTRING
: strings themselves, ou se um valor pode ser interpretado como um número, esse valor pode ser manipulado com comandos de números.
Hashes são ótimas estruturas de dados para armazenar objetos que você pode mapear uma chave para um valor. Eles são otimizados para usar a memória com eficiência e procurar dados muito rapidamente. Em um Hash, tanto o nome do campo quanto o valor são Strings. Portanto, um Hash é um mapeamento de uma String para uma String.
Internamente, um Hash pode ser um ziplist
ou um hash table
. Um ziplist
é uma dually linked list projetada para economizar memória. Em um ziplist
, os inteiros são armazenados como inteiros reais em vez de uma sequência de caracteres. Embora um ziplist
tenha otimizações de memória, as pesquisas não são realizadas em tempo constante. Por outro lado, um hash table
tem pesquisa de tempo constante, mas não é otimizada para memória.
Instagram had to back-reference 300 million media IDs to user IDs, and they decided to benchmark a Redis prototype using Strings and Hashes. The String solution used one key per media ID and around 21 GB of memory. The Hash solution used around 5 GB with some configuration tweaks. The details can be found at https://instagram-engineering.com/storing-hundreds-of-millions-of-simple-key-value-pairs-in-redis-1091ae80f74c
Os Hash são armazenados de forma que ocupem menos espaço e cada hash no Redis pode armazenar até 2^32 pares de chave-valor, ou seja, mais de 4 bilhões.
Os comandos no Redis para os Hashes podem ser categorizados nas seguintes partes:
-
Setters e Getters:
-
HSET key field value [field value ...]
: Armazena um hash com o campo e seu respectivo valor. Caso o hash e o campo já existam, o valor é sobrescrito;redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HGET myhash field1 # "Hello"
-
HGET key field
: Retorna o valor associado ao argumentofield
no hash;redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HGET myhash field1 # "Hello" redis> HGET myhash field2 # "World" redis> HGET myhash field3 # (nil)
-
HGETALL key
: Retorna todos os campos e seus respectivos valores associados a um hash;redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HGETALL myhash # 1) "field1" # 2) "Hello" # 3) "field2" # 4) "World"
-
HMGET key field [field ...]
: Retorna os valores de todos os campos informados que são associados a um hash;redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HMGET myhash field1 field2 nofield # 1) "Hello" # 2) "World" # 3) (nil)
-
HVALS key
: Retorna todos os valores da hash;redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HVALS myhash # 1) "Hello" # 2) "World"
-
HSETNX key field value
: Define o campo e seu valor, apenas se o campo ainda não existir. Se a chave não existir, uma nova chave contendo um hash será criada. Se o campo já existe, esta operação não tem efeito;redis> DEL myhash redis> HSETNX myhash field "Hello" # (integer) 1 redis> HSETNX myhash field "World" # (integer) 0 redis> HGET myhash field # "Hello" # 1) "Hello" # 2) "World"
-
HKEYS key
: Retorna todos os campo da hash;redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HKEYS myhash # 1) "field1" # 2) "field2"
-
-
Data Clean:
-
HDEL key field [field ...]
: Remove o(s) campo(s) e seu(s) respectivo(s) valor(es) do hash informado;
redis> DEL myhash redis> HSET myhash field1 "Hello" field2 "World" # (integer) 2 redis> HDEL myhash field1 field2 nofield # (integer) 2
-
-
Utility:
-
HEXISTS key field
: Determina se o campo do argumentofield
existe na chave hash do argumentokey
;redis> DEL myhash redis> HSET myhash field1 "Hello" # (integer) 2 redis> HEXISTS myhash field1 # (integer) 1 redis> HEXISTS myhash field2 # (integer) 0
-
HINCRBY key field increment
: Incrementa ou decrementa o valor (número inteiro) do campo associado a uma chave conforme o valor do incremento; -
HINCRBYFLOAT key field increment
: Incrementa ou decrementa o valor (número de ponto flutuante) do campo associado a uma chave conforme o valor do incremento; -
HLEN key
: Retorna a quantidade de campos que um hash possui;
-
Bitmaps
Um Bitmap não é um tipo de dados real no Redis. Por baixo, um Bitmap é uma String. Também podemos dizer que um Bitmap é um conjunto de operações de bits em uma String. No entanto, vamos considerá-los como tipos de dados porque o Redis fornece comandos para manipular Strings como Bitmaps. Os Bitmaps também são conhecidos como array de bits ou bitsets.
Um Bitmap é uma sequência de bits em que cada bit pode armazenar 0
ou 1
. Você pode pensar em um Bitmap como uma array de zeros e uns. A documentação do Redis se refere aos índices de Bitmap como offsets. O domínio do aplicativo determina o que cada índice de Bitmap significa.
Os Bitmaps são eficientes em termos de memória, suportam pesquisas rápidas de dados e podem armazenar até 2^32 bits (mais de 4 bilhões de bits).
Veja este exemplo do Bitmap com três bits ativados e dois desativados:
Para ver como um Bitmap pode ser eficiente em termos de memória, vamos comparar um Bitmap a um Set. O cenário de comparação é um aplicativo que precisa armazenar todos os IDs de usuário que visitaram um site em um determinado dia (o offset do Bitmap representa um ID de usuário). Presumimos que nosso aplicativo tenha 5 milhões de usuários no total, mas apenas 2 milhões de usuários visitaram o site naquele dia, e que cada ID de usuário pode ser representado por 4 bytes (32 bits, que é o tamanho de um número inteiro em um computador de 32-bit).
A tabela a seguir compara quanta memória um Bitmap e uma implementação de Set levaria para armazenar 2 milhões de IDs de usuário. Neste exemplo, a chave Redis é a data das visitas:
Redis key | Data type | Amount of bits per user | Stored users | Total memory |
---|---|---|---|---|
visits:2015-01-01 | Bitmap |
1 bit | 5 million | 1 * 5000000 bits = 625kB |
visits:2015-01-01 | Set |
32 bits | 2 million | 32 * 2000000 bits = 8MB |
Os Bitmaps são tipos especiais de estrutura de dados com espaço eficiente, usados para armazenar tipos especiais de informações. Os Bitmaps são usados especialmente para trabalho de análise em tempo real. Embora o Bitmap só possa armazenar valores em binário (1
ou 0
), o fato de que eles consomem menos espaço e o desempenho para obter um valor é O(1)
, os torna muito atraentes para análises em tempo real:
Manipulando
Use SETBIT
para definir o valor do bit em um Bitmap no offset específico.
SETBIT key offset value
: Define ou clears o bit no offset. O bit é cleared ou apagado dependendo do valor, que pode ser 0
ou 1
; Define o valor do bit de um offset de uma chave;
redis> DEL mykey
redis> SETBIT mykey 7 1 # (integer) 0
redis> GETBIT mykey 7 # (integer) 1
redis> SETBIT mykey 7 0 # (integer) 1
redis> GETBIT mykey 7 # (integer) 1
redis> GETBIT mykey 0 # (integer) 0
redis> GETBIT mykey 100 # (integer) 0
GETBIT key offset
: Recupera o valor do bit armazenado para um determinado offset;
Para retornar o número de bits definido como 1
na chave de Bitmap, use o comando BITCOUNT
.
redis> DEL mykey
redis> SETBIT mykey 7 1 # (integer) 0
redis> SETBIT mykey 8 1 # (integer) 0
redis> SETBIT mykey 9 1 # (integer) 0
redis> SETBIT mykey 10 1 # (integer) 0
redis> SETBIT mykey 11 0 # (integer) 0
redis> SETBIT mykey 12 0 # (integer) 0
redis> BITCOUNT mykey # (integer) 4
BITOP
é o comando para realizar operações bit a bit entre Bitmaps. O comando suporta quatro operações bit a bit: AND
, OR
, XOR
e NOT
. O resultado será armazenado em uma chave de destino.
redis> DEL mykey1 mykey2 mykey
redis> SETBIT mykey1 7 1 # (integer) 0
redis> SETBIT mykey1 8 1 # (integer) 0
redis> SETBIT mykey1 9 0 # (integer) 0
redis> SETBIT mykey1 10 0 # (integer) 0
redis> SETBIT mykey2 7 1 # (integer) 0
redis> SETBIT mykey2 8 1 # (integer) 0
redis> SETBIT mykey2 9 1 # (integer) 0
redis> SETBIT mykey2 10 1 # (integer) 0
redis> SETBIT mykey2 11 1 # (integer) 0
redis> BITOP AND mykey mykey1 mykey2 # (integer) 2
redis> BITCOUNT mykey # (integer) 2
redis> BITOP OR mykey mykey1 mykey2 # (integer) 2
redis> BITCOUNT mykey # (integer) 5
Persistência
Como o Redis armazena dados na memória, todos eles são perdidos quando o servidor é reinicializado. Do ponto de vista da redundância de dados, a replicação pode ser usado como uma maneira de fazer backup.
Para manter os dados seguros, Redis fornece mecanismos para persistir dados no disco. Existem duas opções de persistência dos dados: RDB (Redis Database) e AOF (Append Only File). A persistência RDB executa snapshots point-in-time do seu conjunto de dados em intervalos especificados, perfeito para backups e recuperação de desastres. A persistência AOF registra todas as operações de gravação recebidas pelo servidor, que serão reproduzidas novamente em sua inicialização, reconstruindo o conjunto de dados original. Os comandos são registrados usando o mesmo formato que o próprio protocolo Redis, de maneira append-only. O Redis é capaz de reescrever o log em background quando fica muito grande.
Manipulando RDB
Para um armazenamento de dados na memória, como o Redis, habilitar recursos de persistência é a melhor defesa contra perda de dados. Uma maneira óbvia de implementar a persistência é tirar um snapshot da memória onde os dados são armazenados de tempos em tempos. É basicamente assim que o RDB funciona no Redis.
Principais comandos
Para habilitar a persistência RDB para uma instância Redis em execução, chame o comando CONFIG SET
da seguinte maneira:
127.0.0.1:6379> CONFIG SET save "900 1"
# OK
127.0.0.1:6379> CONFIG SET save "900 1 300 10 60 10000"
# OK
Para desativar o recurso de persistência RDB para uma instância Redis em execução, adicione uma string vazia à opção save
:
127.0.0.1:6379> CONFIG SET save ""
# OK
Para verificar se o recurso RDB está ativado, obtenha o parâmetro de save
no redis-cli
. Se houver uma string vazia na resposta do comando CONFIG GET save
, isso indica que o recurso RDB está desativado. Caso contrário, a política de trigger do snapshotting será executada:
127.0.0.1:6379> CONFIG GET save
# 1) "save"
# 2) ""
#
# OR
#
127.0.0.1:6379> CONFIG GET save
# 1) "save"
# 2) "900 1 300 10 60 10000"
Para executar um snapshot RDB manualmente, chame o comando SAVE
no redis-cli
. O redis-cli
ficará bloqueado por um tempo e, em seguida, o Prompt de Comando retorna o seguinte:
127.0.0.1:6379> SAVE
# OK
Alternativamente, podemos chamar também BGSAVE
para realizar um dumping RDB non-blocking:
127.0.0.1:6379> BGSAVE
# Background saving started
Para saber as métricas e o status de persistência, execute INFO Persistence
no redis-cli
:
127.0.0.1:6379> INFO Persistence
# Persistence
loading:0
current_cow_size:0
current_cow_size_age:0
current_fork_perc:0.00
current_save_keys_processed:0
current_save_keys_total:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1634267105
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:262144
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
module_fork_in_progress:0
module_fork_last_cow_size:0
Entendendo como funciona
O RDB funciona como uma câmera para a memória de dados do Redis. Assim que o gatilho da política save
puder ser executado, ela tirará uma foto dos dados no Redis dumping todos os dados em um arquivo no disco local. Antes de introduzir esse processo em detalhes, primeiro explicaremos o valor da opção save
, que determina o gatilho da política do RDB mencionada na seção anterior.
Para o exemplo anterior, 900 1
significa que, pelo menos 1
chave tenha mudado dentro do período de 900 segundos
, um snapshot RDB será tirado. Pode haver mais de uma política na opção save
para controlar a frequência com que o snapshot RDB é tirado. Isso significa que dumping os dados no Redis após x segundos
se pelo menos y chaves
tiverem sido alteradas e nenhum processo de dumping estiver em andamento.
Podemos iniciar manualmente um processo de dumping RDB emitindo os comandos SAVE
ou BGSAVE
. A diferença entre esses dois comandos é que o primeiro inicia uma operação síncrona, o que significa que a thread principal do Redis faz o dumping, enquanto o último executa o dumping em background. Você nunca deve usar SAVE
em seu ambiente de produção porque ele bloqueará o Redis Server. Em vez disso, com o BGSAVE
, a thread principal continua processando os comandos enquanto um processo filho é criado por meio do fork()
e, em seguida, salva o arquivo de dumping em um arquivo temporário chamado temp-<bgsave-pid>.rdb
. Quando o processo de dumping terminar, esse arquivo temporário será renomeado para o nome definido no parâmetro dbfilename
no diretório especificado pelo parâmetro dir
na configuração Redis para substituir o dumping antigo.
Ao listar os processos com o comando ps
, você pode ver o processo filho com o nome redis-rdb-bgsave
, que é bifurcado pelo Redis Server para executar o BGSAVE
. Este processo filho salva todos os dados no momento em que o comando BGSAVE
é processado. Graças ao mecanismo Copy-On-Write
(COW), não há necessidade de o processo filho usar a mesma quantidade de memória que o Redis Server.
Durante o processo de dumping, podemos usar o comando INFO Persistence
para obter as métricas da persistência contínua. O valor de rdb_bgsave_in_progress
quando for 1
, indica que o dumping está em andamento. O valor de rdb_current_bgsave_time_sec
é o tempo que o BGSAVE
está em andamento.
Depois que o processo termina de substituir o arquivo de dump antigo, ela registra uma mensagem com base na quantidade de dados que o processo usou da seguinte maneira:
30:C 15 Oct 2021 18:30:26.310 * RDB: 102 MB of memory used by copy-on-write
1:M 15 Oct 2021 18:30:26.348 * Background saving terminated with success
Depois que o BGSAVE
terminar, o status do último BGSAVE
será salvo na métrica rdb_last_bgsave_status
, e a data/hora Unix do último salvamento bem-sucedido é salvo em rdb_last_save_time
:
127.0.0.1:6379> INFO Persistence
# Persistence
rdb_last_save_time:1634322626
rdb_last_bgsave_status:ok
O dump gerado pelos comandos SAVE
ou BGSAVE
pode ser usado como um arquivo de backup de dados. Você pode utilizar o crontab
para copiar periodicamente o arquivo RDB para um diretório ou sistema de arquivos distribuídos, como o Amazon S3, para fins de restauração posterior:
cp /data/dump.rdb /somewhere/safe/dump.$(date +%Y%m%d%H%M).rdb
Para restaurar um snapshot RDB, você precisa copiar o arquivo para o local especificado pelo parâmetro dir
(127.0.0.1:6379> CONFIG GET dir
) na configuração do Redis e definir a permissão de leitura/gravação desse arquivo para o usuário que inicia a instância Redis. Depois disso, você precisa interromper a instância executando o comando SHUTDOWN NOSAVE
e renomear o novo arquivo de dump para o nome definido pelo parâmetro dbfilename
(127.0.0.1:6379> CONFIG GET dbfilename
). Com uma reinicialização, o conjunto de dados é carregado no Redis a partir do arquivo de backup.
Manipulando AOF
No tópico anterior, aprendemos sobre a opção RDB para persistência de dados no Redis. No entanto, usar RDB para persistência não fornece uma durabilidade muito forte. Como mencionado, um dump de dados RDB contém apenas um snapshot de dados point-in-time do Redis. Embora o Redis dumps dados no arquivo RDB periodicamente, os dados entre os dois dumps RDB serão perdidos permanentemente quando um processo Redis travar ou houver uma falha de hardware. AOF é um arquivo de log append-only que registra os comandos de gravação do Redis Server. A durabilidade dos dados no AOF é maior do que no RDB, porque cada comando de gravação é anexado ao arquivo. Neste tópico, mostraremos como ativar o AOF no Redis e introduziremos alguns parâmetros de configuração importantes do AOF.
Principais comandos
As etapas para manipular o AOF são as seguintes:
Para habilitar a persistência AOF para uma instância Redis em execução, execute o comando CONFIG SET
da seguinte maneira:
127.0.0.1:6379> CONFIG SET appendonly yes
# OK
Se você quiser ativar o AOF permanentemente, adicione appendonly yes
ao arquivo de configuração do Redis e reinicie o servidor:
cat redis.conf | grep "^appendonly" appendonly yes
Para desativar o recurso de persistência AOF para uma instância Redis em execução, defina appendonly
como no
:
redis-cli config set appendonly no
# OK
Para desativar a persistência AOF permanentemente, basta definir appendonly no
no arquivo de configuração e reiniciar o servidor:
cat redis.conf | grep "^appendonly" appendonly no
Para verificar se o recurso AOF está ativado, podemos usar INFO PERSISTENCE
e procurar os itens AOF:
127.0.0.1:6379> INFO PERSISTENCE
# # Persistence
# loading:0
# ...
# aof_enabled:1
# aof_rewrite_in_progress:0
# aof_rewrite_scheduled:0
# aof_last_rewrite_time_sec:0
# aof_current_rewrite_time_sec:-1
# aof_last_bgrewrite_status:ok
# aof_last_write_status:ok
# aof_last_cow_size:225280
# module_fork_in_progress:0
# module_fork_last_cow_size:0
Entendendo como funciona
Quando a opção AOF estiver ativada, o Redis criará o arquivo AOF. O nome de arquivo AOF padrão é appendonly.aof
, que pode ser alterado definindo o parâmetro appendfilename
na configuração .conf
. O Redis também preencherá o arquivo AOF com os dados atuais na memória.
Sempre que o Redis receber um comando de gravação que resultará em uma mudança real dos dados na memória, ele também adicionará o comando ao arquivo AOF. No entanto, se analisarmos mais profundamente o processo de gravação do arquivo, o sistema operacional realmente manterá um buffer no qual os comandos do Redis serão gravados primeiro. Os dados no buffer precisam ser liberados no disco para serem salvos permanentemente. Este processo é feito pela API de chamada de sistema Linux fsync()
, que é uma chamada de bloqueio até que o disco relate que os dados no buffer foram completamente liberados.
Podemos ajustar a frequência de chamar fsync()
ao anexar comandos ao arquivo AOF. Isso é feito com o parâmetro de configuração Redis appendfsync
, e há três opções:
-
always
:fsync()
será chamado para cada comando de gravação. Esta opção garante que apenas um comando será perdido em caso de falha inesperada no servidor ou falha de hardware. No entanto, comofsync()
é uma chamada de bloqueio, o desempenho do Redis será limitado pelo desempenho de gravação do disco físico. Não é aconselhável definirappendfsync
comoalways
porque o desempenho do Redis será degradado significativamente. -
everysec
:fsync()
será chamado pelo Redis uma vez por segundo. Com essa opção, apenas um segundo dos dados será perdido em qualquer evento desastroso inesperado. Muitas vezes, é recomendável que você use essa opção para equilibrar a durabilidade e o desempenho dos dados. -
no
:fsync()
nunca será chamado pelo Redis. Esta opção deixa o sistema operacional decidir quando liberar os dados do buffer para o disco. Na maioria dos sistemas Linux, a frequência é a cada 30 segundos.
Quando o Redis Server estiver sendo encerrado, fsync()
será chamado explicitamente para garantir que todos os dados de gravação no buffer sejam liberados para o disco.
O arquivo AOF será usado para restaurar os dados quando o Redis Server estiver sendo iniciado. O Redis apenas reproduz o arquivo lendo os comandos e aplicando-os à memória um por um. Os dados serão reconstruídos depois que todos os comandos forem processados.
Enquanto o Redis continua anexando comandos de gravação ao arquivo AOF, o tamanho do arquivo pode crescer significativamente. Isso retardará o processo de repetição quando o Redis estiver iniciando. O Redis fornece um mecanismo para compactar o arquivo AOF com uma reescrita AOF. Como você deve ter adivinhado, algumas das chaves Redis foram excluídas ou expiraram, para que possam ser limpas no arquivo AOF. Os valores para certas chaves Redis foram atualizados várias vezes e apenas o valor mais recente precisa ser armazenado no arquivo AOF. Esta é a ideia básica da compactação dos dados em uma reescrita AOF. Podemos usar o comando BGREWRITEAOF
para iniciar o processo de reescrita ou permitir que o Redis execute uma reescrita AOF automaticamente.
Além de acionar manualmente uma reescrita AOF com o comando BGREWRITEAOF
, também podemos configurar o Redis para executar uma reescrita AOF automaticamente. Os dois parâmetros de configuração a seguir são para esta finalidade:
-
auto-aof-rewrite-min-size
: Uma reescrita AOF não será acionada se o tamanho do arquivo AOF for menor que esse valor. O valor padrão é64 MB
. -
auto-aof-rewrite-percentage
: O Redis se lembrará do tamanho do arquivo AOF após a última operação de reescrita AOF. Se o tamanho atual do arquivo AOF tiver aumentado nesse valor de percentual, outra reescrita AOF será acionada. Definir esse valor como0
desativará a Reescrita Automática AOF. O valor padrão é100
.
O comando INFO PERSISTENCE
fornece muitas informações sobre uma reescrita AOF. Por exemplo, aof_last_bgrewrite_status
indica o status da última operação de reescrita AOF, aof_base_size
é o tamanho do último arquivo AOF,
O arquivo AOF pode estar corrompido ou truncado no final se o sistema operacional travar. O Redis fornece uma ferramenta, redis-check-aof
, que pode ser usada para corrigir o arquivo AOF corrompido. Para corrigir um arquivo AOF, basta executar:
redis-check-aof --fix appendonly.aof