Redis Pub/Sub
Saat real-time app berjalan di multiple server instances, event yang terjadi di server A harus sampai ke client yang terkoneksi di server B. Redis Pub/Sub menghubungkan semua instances.
Problem
// Server A: User Budi connected
// Server B: User Rina connected
// Budi kirim pesan → Server A handles
// Rina harus terima pesan → tapi Rina di Server B!
// Solusi: Redis sebagai message broker
Server A → Redis PUB → Redis SUB → Server B → Rina
Implementation
import Redis from "ioredis";
const pub = new Redis(); // publisher
const sub = new Redis(); // subscriber (dedicated connection)
// Subscribe to channel
sub.subscribe("chat:messages", "chat:typing");
sub.on("message", (channel, message) => {
const data = JSON.parse(message);
if (channel === "chat:messages") {
// Broadcast to local Socket.IO clients
io.to(`ch:${data.channelId}`).emit("message:new", data);
}
});
// Publish (from any server instance)
async function publishMessage(message) {
await pub.publish("chat:messages", JSON.stringify(message));
}
Socket.IO + Redis Adapter
// Easiest way — built-in adapter
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";
const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();
await pubClient.connect();
await subClient.connect();
io.adapter(createAdapter(pubClient, subClient));
// Now io.to("room").emit() works across all servers automatically!
Redis Streams (Alternative)
// Pub/Sub: fire-and-forget (no persistence)
// Streams: persistent, replay-able, consumer groups
// Add to stream
await redis.xadd("events", "*", "type", "message", "data", JSON.stringify(msg));
// Read from stream (consumer group)
await redis.xreadgroup("GROUP", "workers", "worker-1", "COUNT", 10, "STREAMS", "events", ">");