Memorystore é o serviço de cache em memória gerenciado do GCP. Oferece Redis e Memcached totalmente gerenciados, sem necessidade de gerenciar nós, patches ou replicação.

Todos os dados ficam em RAM, com latência de leitura/escrita na casa de microssegundos. Instâncias são acessíveis somente por IP privado dentro da VPC.

Redis vs Memcached

AspectoRedisMemcached
Estruturas de dadosStrings, Hashes, Lists, Sets, Sorted Sets, StreamsApenas strings
ReplicaçãoSim (Standard tier)Não
PersistênciaOpcional (RDB/AOF)Não
Pub/SubSimNão
Lua scriptingSimNão
Quando usarCache avançado, sessões, filas, rate limiting, leaderboardsCache simples de alta velocidade e baixo custo

Para novos projetos, prefira Redis: funcionalidades muito mais ricas.

Memorystore for Redis

Tiers

TierHAPersistênciaRecomendado
BasicNãoNãoDev/testing, cache descartável
StandardSim (réplica automática, failover ~1s)OpcionalProdução

Criar instância

# Instância Standard com 5 GB (produção)
gcloud redis instances create meu-redis \
  --size=5 \
  --region=southamerica-east1 \
  --zone=southamerica-east1-a \
  --replica-zone=southamerica-east1-b \
  --tier=STANDARD \
  --redis-version=redis_7_2 \
  --network=projects/PROJETO/global/networks/minha-vpc
 
# Obter IP de conexão
gcloud redis instances describe meu-redis \
  --region=southamerica-east1 \
  --format="value(host)"

Conexão

import redis
 
# Conexão básica (dentro da VPC)
r = redis.Redis(host="10.x.x.x", port=6379, decode_responses=True)
 
# Com autenticação (AUTH string configurada na instância)
r = redis.Redis(
    host="10.x.x.x",
    port=6379,
    password="minha-senha",
    decode_responses=True
)
 
r.ping()  # True

Padrões comuns

import json, time, functools
 
# Cache de resultado de função com TTL
def cache_redis(ttl=300):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args):
            key = f"{func.__name__}:{':'.join(str(a) for a in args)}"
            cached = r.get(key)
            if cached:
                return json.loads(cached)
            result = func(*args)
            r.setex(key, ttl, json.dumps(result))
            return result
        return wrapper
    return decorator
 
@cache_redis(ttl=600)
def buscar_produto(produto_id: str) -> dict:
    return db.query("SELECT * FROM produtos WHERE id = %s", produto_id)
 
# Sessão de usuário (Hash com TTL)
session_id = "sess-abc123"
r.hset(f"session:{session_id}", mapping={
    "user_id": "123",
    "email": "[email protected]"
})
r.expire(f"session:{session_id}", 3600)
 
dados_sessao = r.hgetall(f"session:{session_id}")
 
# Rate limiting (janela de 1 minuto)
def verificar_rate_limit(ip: str, limite: int = 100) -> bool:
    key = f"rate:{ip}:{int(time.time() // 60)}"
    count = r.incr(key)
    if count == 1:
        r.expire(key, 60)
    return count <= limite
 
# Fila simples com List (FIFO)
r.lpush("fila:emails", json.dumps({"para": "[email protected]", "assunto": "Bem-vindo"}))
item_raw = r.brpop("fila:emails", timeout=5)  # bloqueia até ter item ou timeout
if item_raw:
    item = json.loads(item_raw[1])
 
# Leaderboard com Sorted Set
r.zadd("ranking:global", {"jogador-A": 1500.0, "jogador-B": 2000.0, "jogador-C": 1750.0})
top_10 = r.zrevrange("ranking:global", 0, 9, withscores=True)
posicao = r.zrevrank("ranking:global", "jogador-A")
 
# Pub/Sub
# Publisher
r.publish("canal:pedidos", json.dumps({"tipo": "pedido_criado", "id": "123"}))
 
# Subscriber (em outra thread/processo)
pubsub = r.pubsub()
pubsub.subscribe("canal:pedidos")
for message in pubsub.listen():
    if message["type"] == "message":
        evento = json.loads(message["data"])
        processar(evento)
 
# Contador atômico
r.incr("visitas:home")
r.incrby("estoque:produto-X", -1)

Políticas de eviction

Quando a memória está cheia, o Redis descarta chaves conforme a política configurada:

PolíticaComportamentoQuando usar
noevictionRetorna erro, não descartaCache crítico que não pode perder dados
allkeys-lruRemove chaves menos usadas recentementeCache geral (recomendado)
volatile-lruRemove chaves com TTL, priorizando LRUMix de cache e dados persistentes
allkeys-lfuRemove chaves com menor frequência de usoCargas com hotkeys muito acessadas
volatile-ttlRemove chaves com TTL menorQuando TTL representa prioridade de descarte
gcloud redis instances update meu-redis \
  --region=southamerica-east1 \
  --update-redis-config=maxmemory-policy=allkeys-lru

Import / Export

# Exportar snapshot RDB para GCS
gcloud redis instances export gs://meu-bucket/redis-backup.rdb meu-redis \
  --region=southamerica-east1
 
# Importar de GCS (instância deve estar vazia)
gcloud redis instances import gs://meu-bucket/redis-backup.rdb meu-redis \
  --region=southamerica-east1

Redis Cluster (Memorystore for Redis Cluster)

Para workloads que precisam de > 300 GB ou altíssimo throughput de escrita, o Memorystore oferece Redis Cluster com sharding nativo:

gcloud redis clusters create meu-cluster-redis \
  --shard-count=3 \
  --replica-count=1 \
  --region=southamerica-east1 \
  --network=projects/PROJETO/global/networks/minha-vpc

O cliente precisa usar um cliente compatível com Redis Cluster:

from redis.cluster import RedisCluster
 
rc = RedisCluster(host="10.x.x.x", port=6379, decode_responses=True)
rc.set("chave", "valor")

Memorystore for Memcached

Cache distribuído nativo: múltiplos nós independentes com hash consistente pelo cliente.

gcloud memcache instances create meu-memcached \
  --node-count=3 \
  --node-cpu=1 \
  --node-memory=1GB \
  --region=southamerica-east1
 
# Obter IPs dos nós
gcloud memcache instances describe meu-memcached --region=southamerica-east1
from pymemcache.client.hash import HashClient
 
client = HashClient([
    ("10.0.0.1", 11211),
    ("10.0.0.2", 11211),
    ("10.0.0.3", 11211),
])
 
client.set("chave", b"valor", expire=300)
valor = client.get("chave")

Monitoramento

  • Cloud Monitoring: redis.googleapis.com/stats/memory/usage_ratio, redis.googleapis.com/stats/keyspace_hits
  • Taxa de hit/miss: keyspace_hits / (keyspace_hits + keyspace_misses) (ideal > 95%)
  • Monitorar connected_clients e blocked_clients (filas travadas)

Ver também: gcp | gcp-cloud-functions | gcp-firestore | gcp-cloud-sql | gcp-boas-praticas