Redis Pub/Sub vs Kafka

Redis Pub/Sub na prática

Integrando notification-service (Ruby) com analytics-service (Node) via Redis Pub/Sub.

Avançado 40 min 35 pontos Leitura 0%

Nesta aula você vai

  • Publicar evento notification.sent no Redis Pub/Sub
  • Consumir canal no analytics-service em Node
  • Medir comportamento de evento efêmero quando subscriber cai

Redis Pub/Sub na prática

Objetivos

  • Implementar fluxo real de publicação e assinatura entre dois serviços.
  • Entender por que Pub/Sub não substitui mensageria durável.
  • Adicionar logging útil para operação.

Pré-requisitos

  • Redis ativo no Docker.
  • notification-service (Ruby/Sinatra) e analytics-service (Node/Express) no ar.
  • Variável REDIS_URL configurada.

Conceito

No Pub/Sub do Redis, a mensagem só chega em subscribers conectados no momento da publicação. Se o subscriber estiver offline, perdeu. Isso é ótimo para sinais operacionais de baixa criticidade.

Estrutura de arquivos

services/notification-service/
└── app/
    ├── app.rb
    └── pubsub/publisher.rb
services/analytics-service/
└── src/
    └── redis/
        └── notifications-subscriber.js

Passo a passo

  1. Crie publisher no Ruby em services/notification-service/app/pubsub/publisher.rb:
require "json"
require "redis"
require "securerandom"
require "time"

class Publisher
  def initialize(redis_url)
    @redis = Redis.new(url: redis_url)
  end

  def publish_notification_sent(customer_id:, channel:)
    event = {
      eventId: SecureRandom.uuid,
      type: "notification.sent",
      occurredAt: Time.now.utc.iso8601,
      payload: {
        customerId: customer_id,
        channel: channel
      }
    }

    @redis.publish("notifications.live", JSON.generate(event))
    event
  end
end
  1. Use no endpoint Sinatra (services/notification-service/app/app.rb):
post "/notifications/send" do
  body = JSON.parse(request.body.read)
  event = publisher.publish_notification_sent(
    customer_id: body.fetch("customerId"),
    channel: body.fetch("channel")
  )
  status 202
  JSON.generate(event)
end
  1. Crie subscriber no Node em services/analytics-service/src/redis/notifications-subscriber.js:
import Redis from "ioredis";
import { incrementNotificationsSent } from "../store/metrics-store.js";

const subscriber = new Redis(process.env.REDIS_URL ?? "redis://redis:6379");

export async function startNotificationsSubscriber() {
  await subscriber.subscribe("notifications.live");

  subscriber.on("message", (channel, payload) => {
    if (channel !== "notifications.live") return;
    const event = JSON.parse(payload);
    if (event.type !== "notification.sent") return;
    incrementNotificationsSent();
    console.log("notification.sent recebido", { eventId: event.eventId });
  });
}

Como testar

docker compose up -d redis notification-service analytics-service
curl -s -X POST http://localhost:8004/notifications/send \
  -H "Content-Type: application/json" \
  -d '{"customerId":"c-22","channel":"email"}'
docker compose logs -f analytics-service

Pare o analytics-service, publique de novo e suba novamente: o evento publicado durante a queda não será entregue.

Dicas de projeto

  • Nomeie canais com semântica de domínio (notifications.live).
  • Mantenha payload pequeno no Pub/Sub.
  • Se o evento for crítico, publique também no Kafka.

Erros comuns

  • Assumir replay no Redis Pub/Sub.
  • Não validar JSON de entrada no publisher.
  • Ausência de logs com eventId para rastreio.

Resumo

Você implementou um fluxo Pub/Sub real entre Ruby e Node, observando na prática a principal limitação: sem subscriber conectado, não há entrega.