Cache com Redis no Flask: como implementar passo a passo
Como usar Redis para cachear o user_loader e ganhar performance real em produção.
Por que usar cache?
Toda vez que um usuário autenticado faz uma requisição, o Flask-Login chama o user_loader para buscar os dados no banco. Em uma aplicação com centenas de requisições por segundo, isso vira um gargalo. O cache resolve isso armazenando o resultado em memória, evitando consultas repetidas.
O Redis é um banco de dados em memória, extremamente rápido, e a escolha mais popular para cache em aplicações Python.
pip install redis flask-caching
Configurando o Flask-Caching com Redis
O Flask-Caching é uma extensão que integra o Flask com vários backends de cache, incluindo o Redis.
from flask import Flask
from flask_caching import Cache
app = Flask(__name__)
app.config["CACHE_TYPE"] = "RedisCache"
app.config["CACHE_REDIS_URL"] = "redis://localhost:6379/0"
app.config["CACHE_DEFAULT_TIMEOUT"] = 300
cache = Cache(app)
Com essa configuração, o cache vai armazenar dados no Redis por 5 minutos (300 segundos) por padrão.
Cacheando o user_loader
O grande ganho de performance vem ao cachear a função user_loader. Em vez de consultar o banco a cada requisição, buscamos primeiro no Redis:
import json
@login_manager.user_loader
def load_user(user_id):
chave = f"usuario:{user_id}"
dados_cache = cache.get(chave)
if dados_cache:
return Usuario.from_dict(json.loads(dados_cache))
usuario = Usuario.query.get(int(user_id))
if usuario:
cache.set(chave, json.dumps(usuario.to_dict()))
return usuario
Para isso funcionar, seu modelo precisa dos métodos de serialização:
class Usuario(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True)
nome = db.Column(db.String(80))
def to_dict(self):
return {"id": self.id, "email": self.email, "nome": self.nome}
@staticmethod
def from_dict(dados):
u = Usuario()
u.id = dados["id"]
u.email = dados["email"]
u.nome = dados["nome"]
return u
Invalidando o cache
Cache desatualizado é pior do que não ter cache. Sempre que o usuário atualizar seus dados, você precisa limpar a entrada correspondente no Redis:
@app.route("/perfil", methods=["POST"])
@login_required
def atualizar_perfil():
current_user.nome = request.form["nome"]
db.session.commit()
cache.delete(f"usuario:{current_user.id}")
flash("Perfil atualizado com sucesso.")
return redirect(url_for("perfil"))
Cacheando rotas inteiras
Além do user_loader, você pode cachear o resultado de rotas que não mudam com frequência:
@app.route("/artigos")
@cache.cached(timeout=60, key_prefix="lista_artigos")
def listar_artigos():
artigos = Artigo.query.order_by(Artigo.data.desc()).all()
return render_template("artigos.html", artigos=artigos)
Essa rota só vai consultar o banco uma vez por minuto, independentemente de quantos usuários acessem.
Conclusão
Adicionar cache com Redis é uma das formas mais eficazes de melhorar a performance de uma aplicação Flask. O investimento é baixo: poucas linhas de código e um servidor Redis. O retorno é imediato, especialmente no user_loader, que é chamado em toda requisição autenticada. Lembre-se sempre de invalidar o cache quando os dados mudarem.