Real-time experiences like chat systems, live dashboards, and notifications are now a fundamental part of modern applications. Redis Pub/Sub, when paired with Go's concurrency and performance, offers a fast and efficient way to build such features. In this article, we'll walk through building a simple real-time message broadcasting system using Go and Redis Pub/Sub.
>> Read more: Go for Web Development: How Top Companies Benefit from Golang?
What is Pub/Sub?
Publish/Subscribe (Pub/Sub) is a messaging pattern where the sender (publisher) does not send messages directly to specific receivers. Instead, messages are categorized into channels. Receivers (subscribers) subscribe to channels and receive any message published to those channels.
Key Concepts:
- Publisher: Sends messages to a channel.
- Subscriber: Listens to messages on one or more channels.
- Channel: A named stream of messages.
Why Redis?
Redis is an open-source, in-memory data structure store, often used as a database, cache, and message broker. It's known for its blazing speed and minimal latency—two qualities that are essential for real-time systems.
Why Use Redis for Pub/Sub?
- High Performance: Redis operates entirely in memory, making it ideal for high-throughput, low-latency use cases like messaging.
- Simplicity: Setting up Redis for Pub/Sub is straightforward and requires minimal configuration.
- No External Broker Required: If your application already uses Redis for caching or data storage, Pub/Sub comes built-in—eliminating the need to add another messaging service.
- Multi-language Support: Redis clients exist for nearly every language, including robust support for Go, enabling seamless integration.
- Decoupled Architecture: Redis Pub/Sub allows services to communicate asynchronously, promoting a loosely coupled architecture.
When to Use It
Redis Pub/Sub is perfect for lightweight, ephemeral real-time communication like:
- Live chat and notifications
- Real-time analytics and metrics
- System monitoring and alerts
Limitations
- No Message Durability: Messages are not stored. If a subscriber is offline, it will miss messages.
- No Acknowledgments or Retries: There’s no built-in mechanism for ensuring message delivery or processing.
- Not Ideal for Complex Workflows: Use Redis Streams, Kafka, or RabbitMQ for message queuing, persistence, and consumer groups.
For more robust requirements, Redis Streams or other messaging systems like Kafka or NATS may be better suited.
Setting Up Your Go Environment
Initialize Your Project:
go mod init redis-pubsub-go
Install Redis Client:
go get github.com/redis/go-redis/v9
Create Redis Client:
package main
import (
"context"
"github.com/redis/go-redis/v9"
"log"
"time"
"fmt"
)
var ctx = context.Background()
func createClient() *redis.Client {
return redis.NewClient(&redis.Options{
Addr: "redis:6379",
Password: "", // no password set
DB: 0, // use default DB
})
}
Publisher Function
Here’s a simple function to publish messages:
func publishMessage(rdb *redis.Client, channel string, message string) {
err := rdb.Publish(ctx, channel, message).Err()
if err != nil {
log.Fatalf("Could not publish: %v", err)
}
log.Printf("Published: %s", message)
}
Subscriber Function
This function listens for messages on a specified channel:
func subscribeChannel(rdb *redis.Client, channel string) {
pubsub := rdb.Subscribe(ctx, channel)
defer pubsub.Close()
ch := pubsub.Channel()
log.Printf("Subscribed to channel: %s", channel)
for msg := range ch {
log.Printf("Received message: %s", msg.Payload)
}
}
Demo: Real-Time Notifications
Simulate Publisher:
func main() {
rdb := createClient()
for i := 1; i <= 5; i++ {
publishMessage(rdb, "notifications", fmt.Sprintf("Message #%d", i))
time.Sleep(2 * time.Second)
}
}
Simulate Subscriber:
func main() {
rdb := createClient()
subscribeChannel(rdb, "notifications")
}
Run one instance as publisher, and another as subscriber. You’ll see real-time message broadcasting via Redis.
Expected Output
Publisher logs:
Published: Message #1
Published: Message #2
Published: Message #3
...
Subscriber logs:
Subscribed to channel: notifications
Received message: Message #1
Received message: Message #2
Received message: Message #3
...
Dockerize A Golang App
To simplify local development, you can use Docker Compose to run both Redis and your Go app.
Dockerfile
# syntax=docker/dockerfile:1
FROM golang:1.21-alpine
WORKDIR /app
COPY . .
RUN go mod tidy && go build -o app
CMD ["./app"]
docker-compose.yml
version: '3.8'
services:
redis:
image: redis:7
container_name: redis-server
ports:
- "6379:6379"
restart: unless-stopped
app:
build: .
container_name: go-pubsub-app
depends_on:
- redis
restart: on-failure
How to Run It?
- Make sure you have Docker installed.
- Place your Go app files,
Dockerfile
, anddocker-compose.yml
in the project root. - Run the following command:
docker-compose up --build
This will start Redis and your Go app together. You can split the subscriber and publisher logic into separate services if needed.
Make sure your Go code connects to Redis using redis:6379 since it's the internal hostname within Docker Compose.
Best Practices
- Use
context.WithCancel()
for better control over long-running subscriptions. - Handle reconnection and retries gracefully.
- Avoid using Redis Pub/Sub for mission-critical messaging needs—consider Redis Streams or Kafka for persistence.
>> Explore more: Top 10 Most Popular NoSQL Databases for Developers
Conclusion
With just a few lines of Go and Redis, you can set up a powerful real-time messaging system. Redis Pub/Sub is a great starting point for building lightweight features such as chat systems, notifications, and live updates. For more scalable and persistent systems, consider Redis Streams or a dedicated message broker.
>>> Follow and Contact Relia Software for more information!
- golang
- coding