[Home](../README.md) | Prev: [Hash TTL and keyspace events](06-hash-ttl-and-keyspace-events.md) | Next: [TTL](08-ttl.md) # 7. Pub/Sub Redis Pub/Sub is a broadcast: `PUBLISH channel message` sends the message to whoever is subscribed to the channel *at that moment*, and Redis keeps nothing. The reply to `PUBLISH` is the number of subscribers that received it. ## Boot 4.1 sets up the receiving side Older articles declare a `RedisMessageListenerContainer` bean by hand. Boot 4.1 registers one (`redisMessageListenerContainer`) and enables `@RedisListener`, so a listener is a method ([NewsListener](../src/main/java/com/ankurm/redis/messaging/NewsListener.java)): ```java @RedisListener(topic = "news") void onNews(String body) { ... } ``` [11-pub-sub.txt](output/11-pub-sub.txt) starts with what Boot did: ``` beans of type RedisMessageListenerContainer: [redisMessageListenerContainer] running=true listening=true ``` A topic that contains a glob (`alerts.*`) subscribes with `PSUBSCRIBE`; the channel the message came in on is available as a header (`@Header(PubSubHeaders.CHANNEL) String channel`). The `@RedisListener` attributes, from the jar, are `id`, `container`, `value`, `topic` and `consumes`. A `String` parameter receives the raw body; a `org.springframework.data.redis.connection.Message` parameter did not work in this test, because the adapter tried to parse the payload as JSON (a `StreamReadException` on the text `90% full`). This repository does not investigate why. ## Sending `stringRedisTemplate.convertAndSend(channel, message)` returns the number of receivers: - to a channel nobody listens to: `0`, and the message is gone; - to `news` with the annotation listener: `1`; - after a second listener is added to the same channel through the container, still `1`, because the container subscribes once to the channel and fans out to its listeners in-process. Both listeners received the message. The number is receivers on the Redis side, not listeners on yours. `PUBSUB NUMSUB alerts.disk` is `0` while a pattern subscriber is receiving on `alerts.*`: `NUMSUB` counts channel subscribers only, and `PUBSUB NUMPAT` counts patterns. `PUBLISH` counts both. ## At-most-once [12-pub-sub-lost-message.txt](output/12-pub-sub-lost-message.txt): stop the container, publish, start it again. ``` template.convertAndSend("news", "while you were away") = 0 receivers ... messages the listener has: [] ``` Nothing is queued. That is the design, and it is why Pub/Sub is right for cache invalidation hints and live dashboards, and wrong for anything that must not be lost. For that, look at Redis Streams (not covered in this repository). ## Going deeper - [PubSubTest](../src/test/java/com/ankurm/redis/PubSubTest.java) - [Redis Pub/Sub](https://redis.io/docs/latest/develop/pubsub/) - [Spring Data Redis: Pub/Sub messaging](https://docs.spring.io/spring-data/redis/reference/redis/pubsub.html) [Home](../README.md) | Prev: [Hash TTL and keyspace events](06-hash-ttl-and-keyspace-events.md) | Next: [TTL](08-ttl.md)