Redis

Escalando sua aplicação para suportar milhões

Quem sou eu?

Lucas Santos 

@ll_ucasn

BSc. Computer Science

Redis é um NoSQL

 

Redis é um NoSQL

Not only SQL

Redis é um NoSQL

Not only SQL

Outro tipo de estruturação de dados, diferente da tabular vista nos bancos de dados relactionais

Redis é um armazenador de Key-Value

Redis é um armazenador de Key-Value

Você dá a Key(Chave) junto com o Value(valor) para aquela Key

Redis é um armazenador de Key-Value

Você dá a Key(Chave) junto com o Value(valor) para aquela Key

'nome' : 'Daniela'

Redis é um Data Structure Server

 

 

E o mais incrível: Redis é In-Memory

E o mais incrível: Redis é In-Memory

Seu armazenamento principal é feito na memória RAM

E por quê eu quero meu banco de dados In-Memory?

Aqui está um exemplo de uma operação típica em um MySQL

Agora imagine uma aplicação enviando 1 milhão de requisições onde serão realizadas escritas no Banco de Dados

Como o seu sistema irá reagir ao ver que terá que fazer 1kkk disk I/O de vez

Disk I/O é uma operação extremamente custosa

Gargalo

Em situações de fluxo elevado, isso significa: lentidão, Crashes, Usuários Insatisfeitos

Em situações como essa, Redis e sua tecnologia in-memory é o que irá salvar.

Em situações como essa, Redis e sua tecnologia in-memory é o que irá salvar.

"Mas se eu reiniciar a máquina, vou perder minhas informações? Afinal, memória RAM é volátil"

"Mas se eu reiniciar a máquina, vou perder minhas informações? Afinal, memória RAM é volátil"

A estratégia não é substituir o MySQL pelo Redis. A ideia é adiciona-lo na sua stack.

+

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

O papel do Redis é de Memoria Cache

Redis como Memória Cache

Redis até agora:

  • NoSQL

Redis até agora:

  • NoSQL
  • Key-Value Storing

Redis até agora:

  • NoSQL
  • Key-Value Storing
  • Data Structure Server

Redis até agora:

  • NoSQL
  • Key-Value Storing
  • Data Structure Server
  • In-Memory

Redis até agora:

  • NoSQL
  • Key-Value Storing
  • Data Structure Server
  • In-Memory

E não para por aí.

Data Structure Server

  • O fato do Redis ser organizado por Key-Value não limita o value a ser apenas uma String

Data Structure Server

  • O fato do Redis ser organizado por Key-Value não limita o value a ser apenas uma String
  • Ao invés de uma String, o Value pode ser uma Estrutura de Dados conhecida

Data Structure Server

  • O fato do Redis ser organizado por Key-Value não limita o value a ser apenas uma String
  • Ao invés de uma String, o Value pode ser uma Estrutura de Dados conhecida
> set nome daniela
OK
> get nome
"daniela"

Data Structure Server

  • O fato do Redis ser organizado por Key-Value não limita o value a ser apenas uma String
  • Ao invés de uma String, o Value pode ser uma Estrutura de Dados conhecida

List

  • O Redis implementa a verdadeira List Data Structure (de um ponto de vista teórico)

List

  • O Redis implementa a verdadeira List Data Structure (de um ponto de vista teórico)
  • A implementação é feita usando as Linked Lists

List

  • O Redis implementa a verdadeira List Data Structure (de um ponto de vista teórico)
  • A implementação é feita usando as Linked Lists
  • O que significa que a inserção de novos elementos, tanto no início quanto no fim da lista é feito em tempo constante O(1)

List

  • O Redis implementa a verdadeira List Data Structure (de um ponto de vista teórico)
  • A implementação é feita usando as Linked Lists
  • O que significa que a inserção de novos elementos, tanto no início quanto no fim da lista é feito em tempo constante O(1)​
  • O tempo pra inserir um elemento em uma lista com 10 elementos é o mesmo pra inserir em uma lista com 10 milhões de elementos!

List

  • O Redis implementa a verdadeira List Data Structure (de um ponto de vista teórico)
  • A implementação é feita usando as Linked Lists
  • O que significa que a inserção de novos elementos, tanto no início quanto no fim da lista é feito em tempo constante O(1)​
  • O tempo pra inserir um elemento em uma lista com 10 elementos é o mesmo pra inserir em uma lista com 10 milhões de elementos!
  • Logo, se um cenário exigir largas escalas de inserção de dados em listas, use list

List

> rpush minha_lista rodrigo
(integer) 1
> rpush minha_lista daniela
(integer) 2
> rpush minha_lista lucas
(integer) 3
> rpush minha_lista nadson
(integer) 4
> lrange minha_lista 0 -1
1) "rodrigo"
2) "daniela"
3) "lucas"
4) "nadson"

Sets (conjuntos)

  • Sets são coleções não-ordenadas de String

Sets (conjuntos)

  • Sets são coleções não-ordenadas de String
  • A diferença de Sets para Lists, é que essa Estrutura de Dados permite a aplicação de métodos da teoria de conjuntos em cima dos elementos

Sets (conjuntos)

  • Sets são coleções não-ordenadas de String
  • A diferença de Sets para Lists, é que essa Estrutura de Dados permite a aplicação de métodos da teoria de conjuntos em cima dos elementos
  • intercessão, união, diferença entre conjuntos e mais

Sets (conjuntos)

  • Sets são coleções não-ordenadas de String
  • A diferença de Sets para Lists, é que essa Estrutura de Dados permite a aplicação de métodos da teoria de conjuntos em cima dos elementos
  • intercessão, união, diferença entre conjuntos e mais
  • E também, Sets não permitem elementos repetidos. A inserção de elementos iguais ocasionará em uma única cópia deste elemento

Ordered Sets

  •  A diferença é que esses Sets são ordenados por um valor chamado Score

Ordered Sets

  •  A diferença é que esses Sets são ordenados por um valor chamado Score
  • Apesar de que os elementos não podem se repetir, os Scores podem ser iguais

Ordered Sets

  •  A diferença é que esses Sets são ordenados por um valor chamado Score
  • Apesar de que os elementos não podem se repetir, os Scores podem ser iguais
  • Extremamente performático

Ordered Sets

  •  A diferença é que esses Sets são ordenados por um valor chamado Score
  • Apesar de que os elementos não podem se repetir, os Scores podem ser iguais
  • Extremamente performático
  • Utilizados no mundo real em diversos casos: Leader Board em tempo real

Hashes

  •  Hashes são mapeamentos entre valores em strings e campos em strings

Hashes

  •  Hashes são mapeamentos entre valores em strings e campos em strings
  • São perfeitos pra representar objetos

Hashes

  •  Hashes são mapeamentos entre valores em strings e campos em strings
  • São perfeitos pra representar objetos
  • Exemplo, objeto usuário com vários campos como Nome, Sobrenome, Email...

Hashes

  •  Hashes são mapeamentos entre valores em strings e campos em strings
  • São perfeitos pra representar objetos
  • Exemplo, objeto usuário com vários campos como Nome, Sobrenome, Email...
HMSET user:1000 username antirez password P1pp0 age 34
HGETALL user:1000
HSET user:1000 password 12345
HGETALL user:1000

Hashes

  •  Hashes são mapeamentos entre valores em strings e campos em strings
  • São perfeitos pra representar objetos
  • Exemplo, objeto usuário com vários campos como Nome, Sobrenome, Email...
HMSET user:1000 username antirez password P1pp0 age 34
HGETALL user:1000
HSET user:1000 password 12345
HGETALL user:1000
  • Extremamente performático, cada hash pode armazenar mais de 4 bilhões de campos

O quão rápido é o Redis?

Redis-Benchmark

Simulando 100mil requests

$ redis-benchmark -t set,lpush -n 100000 -q

Simulando 100mil requests

$ redis-benchmark -t set,lpush -n 100000 -q
SET: 74239.05 requests per second
LPUSH: 79239.30 requests per second

Simulando 100mil requests

$ redis-benchmark -t set,lpush -n 100000 -q
SET: 74239.05 requests per second
LPUSH: 79239.30 requests per second

Voltando ao uso do Redis como Cache....

Implementando um simples Redis Cache

Implementando um simples Redis Cache

Implementando um simples Redis Cache

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:sa@localhost/bancodedados2'
db = SQLAlchemy(app)
cache = redis.StrictRedis(host='localhost', port=6379, db=0)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80))
    email = db.Column(db.String(120))

    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username

def createUsers():
    with Timer(verbose=True) as t:
        for x in xrange(0,100000):
            user = User('teste', 'teste')
            db.session.add(user)
        db.session.commit()

def getUsers():
    with Timer(verbose=True) as t:
        users = cache.get('users')
        if not users:
            users = User.query.all()
            cache.set('users', users)

@app.route('/')
def hello_world():
    getUsers()
    return 'Hello Worldd!'

if __name__ == '__main__':
    app.debug=True
    app.run(host='0.0.0.0')

O que irá acontecer?

1º Request: Buscar um número enorme de registros no MySQL e depois adicionar no Redis

1º Request: Buscar um número enorme de registros no MySQL e depois adicionar no Redis

Tempo para retornar os dados: 45861 millisegundos

2º Request: Usuário buscando os mesmo dados, dessa vez ele já está no Redis Cache

2º Request: Usuário buscando os mesmo dados, dessa vez ele já está no Redis Cache

Tempo para retornar os dados: 5 millisegundos

2º Request: Usuário buscando os mesmo dados, dessa vez ele já está no Redis Cache

Tempo para retornar os dados: 5 millisegundos

45861 millisegundos 

->

5 millisegundos

45861 millisegundos 

->

5 millisegundos

9172 vezes mais rápido que o acesso ao MySQL

Meu motivo para usar Redis!

Obrigado!

Redis

By Lucas Nascimento

Redis

  • 838