Mais conteúdo relacionado Semelhante a Redis na Prática (20) Mais de Tiago Albineli Motta (18) Redis na Prática2. Benchmark
3 processos / 20 mil inserções / 60 mil selects ordenados / 60 mil counts
> time ./manage.py benchmark --db=redis
real 2m32.417s
user 2m27.341s
sys 0m3.112s
> time ./manage.py benchmark --db=mysql
real 16m25.251s
user 0m46.115s
sys 0m4.628s
> time ./manage.py benchmark --db=mongodb
^C
KeyboardInterrupt
real 38m28.659s
user 0m59.056s
sys 0m2.628s
3. Benchmark
Nunca confie no Benchmark dos outros!
6. Consolidações
tasks
NewFanTask
TaskManager NewFanTask gunicorn
NewFanTask
ArtistTaskGroup
7. Fila para consolidações
redis> rpush tasks oi
redis> rpush tasks tudo
redis> rpush tasks bem
redis> lpop tasks
"oi"
redis> lpop tasks
"tudo"
redis> lpop tasks
"bem"
redis> lpop tasks
(nil)
8. Cuidado: Fila virando Pilha
redis> rpush tasks oi
redis> rpush tasks tudo
redis> rpush tasks bem
redis> rpop tasks
"bem"
redis> rpop tasks
"tudo"
redis> rpop tasks
"oi"
redis> rpop tasks
(nil)
9. Abstraindo a fila
class RedisQueue(object):
def __init__(self,key,client=client):
self.key = key
self.client = client
def push(self,obj):
value = ujson.encode(obj)
self.client.rpush(self.key, value)
def pop(self):
value = self.client.lpop(self.key)
return self.from_json(value)
11. Exemplo 2: Crawler de vídeo
Dois milhões de músicas
Restrição da API do Youtube
Busca de vídeos no browser
Processamento no server
Prioridade pros mais acessados
12. SortedSet
redis> zincrby crawler-video 1 video1
redis> zincrby crawler-video 1 video1
redis> zincrby crawler-video 1 video2
redis> zincrby crawler-video 8 video3
redis> zrevrange crawler-video 0 -1
1) "video3" 2) "video1" 3) "video2"
redis> zrevrank crawler-video video3
(integer) 0
13. Abstraindo SortedSet
class RedisSortedSet(object):
def __init__(self,key,client=client):
self.key = key
self.client = client
def incr(self,value,amount=1):
return self.client.zincrby(self.key, value, amount)
def bests(self,max=0):
return self.client.zrevrange(self.key, 0, max-1)
15. Utilizando Sets
def responder(self, quiz, resposta):
respondidas = RedisSet(”quiz-respondidos-%s” % self.id, client=redis)
if respondidas.add(quiz.id):
if quiz.opcao_correta(resposta):
acertadas = RedisSet(”quiz-acertadas-%s” % self.id, client=redis)
acertadas.add(quiz.id)
redis> sadd quiz-respondidos-x 1
(integer) 1
redis> sadd quiz-acertadas-x 1
(integer) 1
redis> sadd quiz-respondidos-x 1
(integer) 0
16. Hash
redis> hset estados-capitais amazonas manaus
redis> hset estados-capitais bahia salvador
redis> hgetall estados-capitais
1) "amazonas" 2) "manaus" 3) "bahia" 4) "salvador"
redis> hset estados-capitais amazonas belem
redis> hgetall estados-capitais
1) "amazonas" 2) "belem" 3) "bahia" 4) "salvador"
redis> hsetnx estados-capitais bahia recife
redis> hgetall estados-capitais
1) "amazonas" 2) "belem" 3) "bahia" 4) "salvador"
17. Utilizando Hash
def responder(self, quiz, resposta):
respondidos = RedisHash(”quiz-respondidos-%s” % self.id, client=redis)
acertou = 1 if quiz.opcao_correta(resposta) else 0
respondidos.set_if_new(quiz.id, acertou)
redis> hsetnx quiz-respondidos-x 20 0
(integer) 1
redis> hsetnx quiz-respondidos-x 20 1
(integer) 0
20. Exemplo 4: Ranking do Quiz
Ranking dos amigos?
1 ranking por usuário
Atualizar rankings a cada resposta?
21. Fila e SortedSet
Ao responder um quiz:
redis> rpush tasks rankings-quiz-usuario-x
Cron:
redis> lpop tasks
"rankings-quiz-usuario-x"
redis> smembers amigos-usuario-x
1) "a" 2) "b" 3) "c"
redis> hval respostas-usuario-x
1) "1" 2) "1" 3) "0"
redis> zadd ranking-usuario-x 2 usuario-x
redis> zadd ranking-usuario-a 2 usuario-x
redis> zadd ranking-usuario-b 2 usuario-x
redis> zadd ranking-usuario-c 2 usuario-x
24. OCLs: Multi / Exec
redis> multi
redis> zadd ranking-usuario-x 2 usuario-x
redis> zadd ranking-usuario-a 2 usuario-x
redis> zadd ranking-usuario-b 2 usuario-x
redis> zadd ranking-usuario-c 2 usuario-x
redis> exec
redis = Redis(**confs).pipeline()
for id in [id, ”a”,”b”,”c”]:
sorted_set = RedisSortedSet(”ranking-usuario-%s” % id, client=redis)
sorted_set.add(”usuario-x”,amount=2)
redis.execute()
25. OCLs: Multi / Exec
redis> multi
redis> hsetnx respostas-usuario-id quiz-1 1
redis> rpush tasks rankings-quiz-usuario-x
redis> exec
acertou = 1 if pergunta.certa == resposta else 0
redis = Redis(**confs).pipeline()
hash = RedisHash(”respostas-usuario-%s” % usuario.id, client=redis)
hash.set_if_new(”quiz-” % pergunta.id, acertou):
if acertou:
queue = RedisQueue(”tasks”, client=redis)
queue.push(”ranking-quiz-usuario-%s” % usuario.id)
redis.execute()
26. OCLs: Master / Slave
> sudo vim /etc/redis/redis-slave.conf
port 6380
slaveof 127.0.0.1 6739
> sudo redis-server /etc/redis/redis-slave.conf
> redis-cli
redis> monitor
OK
1335985598.138718 "monitor"
1335986003.209676 "SYNC"
27. OCLs: Master / Slave
> redis-cli
redis 127.0.0.1:6379> set x b
> redis-cli -h 127.0.0.1 -p 6380
redis 127.0.0.1:6380> monitor
OK
1335986423.169745 "monitor"
1335986441.430632 "PING"
1335986441.430632 "PING"
1335986462.113501 "set" "x" "b"
1335986471.500976 "PING"
28. OCLs: Script em lua
Redis 2.6:
redis> eval "return {ARGV[1]}" valor
Ainda não usei, por isso não vou falar nada.
29. Conclusão
Performático
Escalável
Divertido
No entando...
+ Complexo que Sql e Mongo