redis na prática
TRANSCRIPT
Redis na prtica
O ruim, o bom e o sensacional
Benchmark
3 processos / 20 mil inseres / 60 mil selects ordenados / 60 mil counts
> time ./manage.py benchmark --db=redisreal 2m32.417suser2m27.341ssys0m3.112s
> time ./manage.py benchmark --db=mysqlreal16m25.251suser0m46.115ssys0m4.628s
> time ./manage.py benchmark --db=mongodb^CKeyboardInterruptreal38m28.659suser0m59.056ssys0m2.628s
Benchmark
Nunca confie no Benchmark dos outros!
Exemplos
Tornar-se f
Crawler de vdeo
Responder Quiz
Ranking do Quiz
Exemplos 1: Tornar-se F
Muitas consolidaes a cada novo f
Rapidez para no bloquear processos
Consolidaes
tasks
gunicornTaskManager
NewFanTaskNewFanTaskNewFanTask
ArtistTaskGroup
Fila para consolidaes
redis> rpush tasks oiredis> rpush tasks tudoredis> rpush tasks bem
redis> lpop tasks"oi"redis> lpop tasks"tudo"redis> lpop tasks"bem"redis> lpop tasks(nil)
Cuidado: Fila virando Pilha
redis> rpush tasks oiredis> rpush tasks tudoredis> rpush tasks bem
redis> rpop tasks"bem"redis> rpop tasks"tudo"redis> rpop tasks"oi"redis> rpop tasks(nil)
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)
Porque no?
Resque / Pyres
Redis Pub/Sub
Exemplo 2: Crawler de vdeo
Dois milhes de msicas
Restrio da API do Youtube
Busca de vdeos no browser
Processamento no server
Prioridade pros mais acessados
SortedSet
redis> zincrby crawler-video 1 video1redis> zincrby crawler-video 1 video1redis> zincrby crawler-video 1 video2redis> zincrby crawler-video 8 video3
redis> zrevrange crawler-video 0 -11) "video3" 2) "video1" 3) "video2"
redis> zrevrank crawler-video video3(integer) 0
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)
Exemplo 3: Responder Quiz
Gravar se acertou ou no
Impedir responder mesma pergunta
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) 1redis> sadd quiz-acertadas-x 1(integer) 1
redis> sadd quiz-respondidos-x 1(integer) 0
Hash
redis> hset estados-capitais amazonas manaus
redis> hset estados-capitais bahia salvador
redis> hgetall estados-capitais1) "amazonas" 2) "manaus" 3)
"bahia" 4) "salvador"
redis> hset estados-capitais amazonas belem
redis> hgetall estados-capitais1) "amazonas" 2) "belem" 3)
"bahia" 4) "salvador"
redis> hsetnx estados-capitais bahia recife
redis> hgetall estados-capitais1) "amazonas" 2) "belem" 3)
"bahia" 4) "salvador"
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
Exemplo 4: Ranking do Quiz
Sugestes?
Exemplo 4: Ranking do Quiz
Sugestes?
SortedSet?
Exemplo 4: Ranking do Quiz
Ranking dos amigos?
1 ranking por usurio
Atualizar rankings a cada resposta?
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-x1) "a" 2) "b" 3) "c"redis> hval respostas-usuario-x1) "1" 2) "1" 3) "0"redis> zadd ranking-usuario-x 2 usuario-xredis> zadd ranking-usuario-a 2 usuario-xredis> zadd ranking-usuario-b 2 usuario-xredis> zadd ranking-usuario-c 2 usuario-x
Muito complexo?
Porque no MySql?
Cansei de exemplos
Vamos falar de OCLs
OCLs: Multi / Exec
redis> multiredis> zadd ranking-usuario-x 2 usuario-xredis> zadd ranking-usuario-a 2 usuario-xredis> zadd ranking-usuario-b 2 usuario-xredis> zadd ranking-usuario-c 2 usuario-xredis> 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()
OCLs: Multi / Exec
redis> multiredis> hsetnx respostas-usuario-id quiz-1 1redis> rpush tasks rankings-quiz-usuario-xredis> exec
acertou = 1 if pergunta.certa == resposta else 0redis = 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()
OCLs: Master / Slave
> sudo vim /etc/redis/redis-slave.confport 6380 slaveof 127.0.0.1 6739> sudo redis-server /etc/redis/redis-slave.conf
> redis-cliredis> monitorOK1335985598.138718 "monitor"1335986003.209676 "SYNC"
OCLs: Master / Slave
> redis-cli redis 127.0.0.1:6379> set x b
> redis-cli -h 127.0.0.1 -p 6380redis 127.0.0.1:6380> monitorOK1335986423.169745 "monitor"1335986441.430632 "PING"1335986441.430632 "PING"1335986462.113501 "set" "x" "b"1335986471.500976 "PING"
OCLs: Script em lua
Redis 2.6:
redis> eval "return {ARGV[1]}" valor
Ainda no usei, por isso no vou falar nada.
Concluso
Performtico
Escalvel
Divertido
No entando...+ Complexo que Sql e Mongo
Mais informaes
http://redis.io/commands
http://rediscookbook.org
Mantenha contato
@timotta
http://programandosemcafeina.blogspot.com
Muokkaa otsikon tekstimuotoa napsauttamalla
Muokkaa jsennyksen tekstimuotoa napsauttamallaToinen jsennystasoKolmas jsennystasoNeljs jsennystasoViides jsennystasoKuudes jsennystasoSeitsems jsennystasoKahdeksas jsennystasoYhdekss jsennystaso