Messaging Fanout Pattern for Valkey and Redis
Distributed systems, spread across multiple nodes, depend on efficient, reliable communication between different services. Java developers who build distributed applications often rely on message queues to decouple services and implement asynchronous processing.
However, queues are designed for work distribution, not message broadcasting. Things can get complicated quickly when a single message needs to be delivered to multiple consumers simultaneously. Imagine, for example, a scenario where your distributed application needs a critical update, such as a price change to a popular product in your online store.
The change needs to be communicated immediately to multiple distinct services, such as the product catalog, a search index, and a notification system, among others. A developer might have a “PriceUpdate” queue for events like this, but the standard behavior for most message brokers is to deliver that message to one of the available consumers. The first service that picks up the message consumes it.
Introducing the Message Fanout Pattern
In scenarios like the one described above, not all services may receive the update message or the Java developer may need to code business logic to ensure they do. A more elegant solution is the message fanout pattern.
With message fanout, a single message is broadcast to multiple consumers who have expressed interest in receiving such messages. Instead of one message being consumed by a single consumer from the queue, fanout is far more flexible because it offers:
- One-to-many delivery: A single published message is delivered to all subscribed consumers.
- Decoupling: Publishers don’t need to know about the individual subscribers, only about the central distribution mechanism. Subscribers also don’t need to know about the publisher.
- Parallel processing: Multiple consumers can process the same message concurrently, enabling high scalability for certain types of workloads.
Message Fanout Use Cases
The message fanout pattern is versatile, making it ideal for numerous real-world scenarios. Consider these use cases:
- Real-time notifications: Fanout can send alerts or updates to multiple users or services.
- Cache invalidation: A fanout pattern is perfect for broadcasting messages to multiple nodes to invalidate outdated cache entries.
- Data replication: It can also distribute changes to multiple replicas or data stores.
While it’s easy to see how developers might implement the fanout pattern, building a reliable fanout mechanism that guarantees message delivery and handles errors or failures could be a time-consuming task. This is where Redisson PRO's Reliable Fanout feature comes in,
Redisson PRO: Connecting Java Apps to Valkey/Redis Messaging
Redisson PRO is a Valkey and Redis client built for Java developers. Through familiar classes, methods, and objects, developers can tap into the powerful messaging capabilities of Valkey or Redis. Among Redisson PRO’s extensive features is the Reliable Fanout object, which ensures message delivery to multiple ReliableQueue objects in a publish-subscribe (pub/sub) model.
With Reliable Fanout, every published message is sent to each queue subscribed to the same fanout object. All fanout operations are executed atomically to ensure data consistency and prevent race conditions.
Code Samples
To see how easy Redisson PRO makes it to implement Reliable Fanout, here are a few code samples. Using the example scenario mentioned earlier, here’s how a price update event is sent to multiple services.
import org.redisson.api.RFanOutManager;
import org.redisson.api.RedissonClient;
import org.redisson.api.RReliableQueue;
public class MessagePublisher {
public static void main(String[] args) {
RedissonClient redisson = ...
// Get the Fanout Manager
RReliableFanout fanout = redisson.getReliableFanout("fanout");
// The message to be published
String message = "Important Update: Product XYZ price changed!";
fanout.publish(FanoutPublishArgs.messages(MessageArgs.payload(message).header("key12", "value3")));
System.out.println("Message published via fanout.");
}
}
Each service interested in the update messages should use one of Redisson PRO’s RReliableQueue
instances. The fanout service distributes the messages to each queue. In this code sample, the service for product catalog updates is subscribed:
import org.redisson.api.RReliableQueue;
import org.redisson.api.RedissonClient;
public class ProductCatalogSubscriber {
public static void main(String[] args) throws InterruptedException {
RedissonClient redisson = ...
RReliableFanout fanout = redisson.getReliableFanout("fanout");
// subscribe queue with "test" name
fanout.subscribeQueue("test");
// or subscribe queue with "test" name and filter
fanout.subscribeQueue("test", (value, headers) -> {
return headers.containsKey("key12") || value.equals(1);
});
RReliableQueue rq = redisson.getReliableQueue("test");
Message msg = rq.poll();
msg.getPayload(); // message content
rq.acknowledge(QueueAckArgs.ids(msg.getId()));
}
}
Broadcast Your Messages With Messaging Fanout for Valkey and Redis
For applications that require one-to-many message delivery, the messaging fanout pattern is the most reliable and flexible option available. Backed by the speed and robust features of Valkey or Redis, Redisson PRO allows Java developers to use familiar classes, methods, and APIs to implement Reliable Fanout quickly.