alocar mais memória e, em consequência, terá o servidor bloqueado por
um tempo. Caso precise de mais detalhes sobre isso, verifique o link a
seguir:
http://redis.io/commands/setbit
Os usuários são representados pelo seu código, que no nosso exemplo
são os números 1000, 1001 e 1002. Já o parâmetro final (número 1) utilizado em cada comando é o que chamados de bit, ele serve para sinalizar que o usuário de fato clicou no anúncio. Pense nele como um valor binário, o que é verdade pois esse parâmetro só pode receber o valor 0 ou 1 (podemos pensar
nele como TRUE ou FALSE). Ou seja, quando definimos o valor do bit
como 1 significa que o usuário efetuou o clique e se (re)definirmos seu valor para 0 significa que o usuário não clicou no anúncio ou que o seu clique foi invalidado por algum motivo. Agora vamos realizar outros comandos:
127.0.0.1:6379> KEYS *
1) "cliques:anuncio:CASADOCODIGO"
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 1000
(integer) 1
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 1001
(integer) 1
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 1002
(integer) 1
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 8888
(integer) 0
O primeiro comando executado, como já sabemos, serve apenas para lis-
tar todas as chaves que existem no Redis. Todas as chaves existentes no Redis foram removidas antes deste exemplo para facilitar a sua compreensão. Note
que uma única chave representa todos os usuários que efetuaram o clique no
39
4.3. Estatísticas de usuários únicos por data
Casa do Código
anúncio CASADOCODIGO. O comando GETBIT recupera o valor do bit ar-
mazenado para um determinado offset (usuário no nosso exemplo). Quando
o usuário informado corresponde a um usuário que efetuou o clique, o valor
do bit é 1, e quando informamos um usuário (8888) que não efetuou o clique, o comando retorna o valor 0.
Para finalizar essa breve introdução aos comandos SETBIT e GETBIT,
vamos invalidar o clique do usuário 1001 e ver o que acontece. Veja isso no seguinte exemplo:
127.0.0.1:6379> SETBIT cliques:anuncio:CASADOCODIGO 1001 0
(integer) 1
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 1000
(integer) 1
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 1001
(integer) 0
127.0.0.1:6379> GETBIT cliques:anuncio:CASADOCODIGO 1002
(integer) 1
Pronto, já tivemos uma breve introdução sobre Bitmaps e como eles fun-
cionam no Redis. Agora vamos voltar ao nosso exemplo. Primeiro criaremos
uma aplicação Java para gerar os dados: vamos simular 1000 acessos de 500
usuários durante um período de 30 dias de um mês e ano predefinido. Veja o
exemplo a seguir:
public class ArmazenarAcessosDosUsuariosComBitmap {
public void armazenar(long codigoDoUsuario, String data) {
Jedis jedis = new Jedis("localhost");
String chave = String.format("acesso:%s", data);
jedis.setbit(chave, codigoDoUsuario, true);
}
public static void main(String[] args) {
int quantidadeDeUsuarios = 500;
int quantidadeDeAcessos = 1000;
int quantidadeDeDias = 30;
40
Casa do Código
Capítulo 4. Redis no mundo real Parte 2
Random random = new Random();
ArmazenarAcessosDosUsuariosComBitmap acesso =
new ArmazenarAcessosDosUsuariosComBitmap();
for(Integer numero=1; numero<=quantidadeDeAcessos; numero++){
long usuario = (random.nextInt(quantidadeDeUsuarios) + 1);
String data = String.format(
"%02d/11/2013",
(random.nextInt(quantidadeDeDias) + 1)
);
acesso.armazenar(usuario, data);
}
}
}
Pronto, agora já temos uma boa quantidade de dados armazenados no
Redis. Repare que novamente utilizamos o comando SETBIT para armaze-
nar nossos dados, sendo que a chave definida para esse exemplo é composta
como acesso:DD/MM/AAAA e o código do usuário foi usado como offset
para nosso Bitmap. Como todos
os dados foram gerados de forma aleatória
devido à classe Java Random, o resultado do exemplo anterior pode variar a
cada execução e afetar diretamente o resultado dos próximos exemplos que
veremos a seguir.
Vamos criar uma aplicação para extrair as informações que precisamos
sobre usuários durante o período de um dia e de uma semana (sete dias).
Veja a aplicação a seguir:
public class ObterDadosAcessoPorDataComBitmap {
public long acessosPorPeriodo(String...datas) {
Jedis jedis = new Jedis("localhost");
long total = 0;
for (String data : datas) {
String chave = String.format("acesso:%s", data);
total += jedis.bitcount(chave);
}
41
4.3. Estatísticas de usuários únicos por data
Casa do Código
return total;
}
public static void main(String[] args) {
ObterDadosAcessoPorDataComBitmap dadosDeAcesso =
new ObterDadosAcessoPorDataComBitmap();
String[] diario = { "05/11/2013" };
String[] semanal = {
"16/11/2013",
"17/11/2013",
"18/11/2013",
"19/11/2013",
"20/11/2013",
"21/11/2013",
"22/11/2013"
};
long totalDiario = dadosDeAcesso.acessosPorPeriodo(diario);
long totalSemanal = dadosDeAcesso.acessosPorPeriodo(semanal);
System.out.println(
String.format(
"Total de usuários únicos no dia %s foi: %d",