Lewati ke konten utama
menjadi.dev
Chapter 17.15 API & Auth Menengah

Redis: Pub/Sub dan Real-time Features

Messaging real-time, streams, dan use cases advanced

Tujuan Pembelajaran

  • Bisa menggunakan Redis Pub/Sub
  • Mengerti Redis Streams
  • Bisa implementasi real-time features

Analogi

Diagram

      Pub/Sub Flow:
Publisher → Redis Channel → [Subscriber 1, Subscriber 2, ...]

Streams Flow:
Producer → Redis Stream → Consumer Group → [Consumer 1, Consumer 2]
    

Pub/Sub untuk broadcast, Streams untuk persistent event log

Penjelasan Konsep

Selain caching, Redis punya fitur real-time yang powerful: Pub/Sub dan Streams.

Kedua fitur ini memungkinkan komunikasi real-time antar bagian aplikasi.

Pub/Sub: Publish dan Subscribe

Pub/Sub adalah pattern messaging di mana publisher mengirim pesan ke channel, dan subscriber yang subscribe ke channel tersebut menerima pesan.

Publisher: PUBLISH notifications:user:100 "Pesan baru!"

Subscriber (sebelumnya): SUBSCRIBE notifications:user:100
→ Menerima: "Pesan baru!"

Karakteristik Pub/Sub Redis:

  • Fire and forget: Pesan tidak disimpan,

Kalau tidak ada subscriber pesan hilang

  • One-to-many: Satu pesan bisa diterima banyak subscriber
  • No persistence: Pesan hanya ada di memory
  • Decoupled: Publisher tidak tahu siapa subscriber

Use cases:

  • Chat application (broadcast message ke room)
  • Real-time notifications
  • Live updates (score, status)
  • Cache invalidation broadcast

Redis Streams: Persistent Event Log

Streams adalah data structure yang lebih advanced daripada Pub/Sub.

Mirip seperti Apache Kafka tapi lebih sederhana:

  • Persistent: Pesan disimpan (tidak hilang seperti Pub/Sub)
  • Ordered: Pesan punya ID dan urutan
  • Consumer groups: Multiple consumers bisa membagi workload
  • Acknowledgment: Pesan harus di-ack setelah diproses
# Producer
XADD orders_stream * order_id 100 status pending

# Consumer (single)
XREAD BLOCK 5000 STREAMS orders_stream $  # Block 5 detik

# Consumer Group
XGROUP CREATE orders_stream processing_group $ MKSTREAM
XREADGROUP GROUP processing_group consumer_1 STREAMS orders_stream >
XACK orders_stream processing_group 1698765432100-0

Pub/Sub di Aplikasi

import { createClient } from 'redis';

const pub = createClient({ url: 'redis://localhost:6379' });
const sub = createClient({ url: 'redis://localhost:6379' });
await pub.connect();
await sub.connect();

// Subscribe
await sub.subscribe('notifications',

(message) => {
  const data = JSON.parse(message);
  console.log('Notifikasi:', data);
  // Kirim ke WebSocket client
});

// Publish
await pub.publish('notifications', JSON.stringify({
  type: 'new_message',
  userId: 100,
  content: 'Halo!'
}));

Membangun Chat dengan Redis Pub/Sub + WebSocket

Kombinasi Redis Pub/Sub dengan WebSocket memungkinkan chat multi-server.

Setiap server subscribe ke channel, dan broadcast ke semua WebSocket client yang terhubung.

Contoh Kode

typescript
// Real-time notification system
import { createClient } from 'redis';

const redis = {
  pub: createClient({ url: 'redis://localhost:6379' }),
  sub: createClient({ url: 'redis://localhost:6379' }),
};

await redis.pub.connect();
await redis.sub.connect();

// Notification service
class NotificationService {
  async send(userId: number, notification: { type: string; message: string }) {
    const channel = `notifications:user:${userId}`;
    const payload = JSON.stringify({
      ...notification,
      timestamp: new Date().toISOString(),
    });
    
    // Publish ke channel
    await redis.pub.publish(channel, payload);
    
    // Simpan ke inbox (untuk user yang offline)
    await redis.lpush(`inbox:user:${userId}`, payload);
    await redis.ltrim(`inbox:user:${userId}`, 0, 99); // Keep last 100
  }
  
  async subscribe(userId: number, onMessage: (msg: any) => void) {
    const channel = `notifications:user:${userId}`;
    await redis.sub.subscribe(channel, (message) => {
      onMessage(JSON.parse(message));
    });
    
    // Kirim unread messages dari inbox
    const inbox = await redis.lrange(`inbox:user:${userId}`, 0, -1);
    inbox.reverse().forEach(msg => onMessage(JSON.parse(msg)));
    await redis.del(`inbox:user:${userId}`); // Clear inbox setelah deliver
  }
  
  async unsubscribe(userId: number) {
    await redis.sub.unsubscribe(`notifications:user:${userId}`);
  }
}

// Usage with WebSocket
const notifService = new NotificationService();

// Saat user connect via WebSocket
ws.on('open', () => {
  notifService.subscribe(userId, (notification) => {
    ws.send(JSON.stringify(notification));
  });
});

Penjelasan Kode

Kombinasi Pub/Sub (real-time) + List inbox (offline persistence) memastikan user tidak ketinggalan notifikasi.

Prompt AI

Bangun sistem chat sederhana dengan Redis Pub/Sub. Gunakan channel per room. Support join/leave room.

Pertanyaan Reflektif

Bandingkan Redis Streams dengan message queue seperti RabbitMQ atau Apache Kafka. Kapan pakai masing-masing?