This is the third and last part of introducing redis using spring-data-redis. In the first part, we have covered redis installation and basic data types of redis. In the second part of this series, we have created a demo java application exploring various data structures using spring-data-redis. In case you had missed it you can revisit first part of the tutorial here and second part here.

In this article, we will cover publish/subscribe messaging paradigm. In publish/subscribe messaging paradigm, message sender publishes the messages on a channel without the knowledge of receiver or subscriber. The subscriber can register for one or more channels and receive only messages of their interest. Redis command SUBSCRIBE is used to subscribing to a channel and PUBLISH to publish a message to the channel. UNSUBSCRIBE command is used for unsubscribing from a channel.Redis PubSub framework also supports pattern matching subscription.

Create a Publisher
Now let us add a publisher class for showcasing redis pub/sub mechanism. For simplicity, we will create a simple interface IRedisPublisher for publishing a message, which will publish toString method of the message object to publish a message to the channel.

1
2
3
4
5
6
package com.wordpress.omanandj.message;
public interface IRedisPublisher {
    public void publish(Object message);
}

Implementation of IRedisPublisher requires attributes a topic and redisTemplate to send the message.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.wordpress.omanandj.message.impl;
import com.wordpress.omanandj.message.IRedisPublisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.stereotype.Component;
@Component
public class RedisMessagePublisher implements IRedisPublisher {
    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private ChannelTopic topic;
    @Override
    public void publish(Object message) {
        redisTemplate.convertAndSend(topic.getTopic(),message.toString());
    }
}

Since RedisMessagePublisher requires a topic, let us add a bean to a topic in application context class AppConfiguration by adding the following skeleton of code to add a channel:

1
2
3
4
5
@Bean
    ChannelTopic createTopic()
    {
        return new ChannelTopic("pubsub:channel");
    }

Create a Subscriber
For defining the redis subscriber, we will use the interface MessageListener provided by spring-data-redis. On receiving a message, we will just print the message to the console for the demo purpose.

1
2
3
4
5
6
7
8
9
10
11
package com.wordpress.omanandj.repository.impl;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
public class RedisMessageSubscriber implements MessageListener {
    @Override
    public void onMessage(Message message, byte[] pattern) {
        System.out.println("Message Received on channel " + message.getChannel() + " message :: " + message.toString() );
    }
}

Now let us define the spring bean configuration for the message subscriber in AppConfiguration. For this first, we have to define a MessageListenerAdapter. Spring bean for MessageListenerAdapter can be defined using RedisMessageSubscriber as:

1
2
3
4
@Bean
    public MessageListenerAdapter messageListenerAdapter() {
          return new MessageListenerAdapter(new RedisMessageSubscriber());
    }

Now we have to define a RedisMessageListenerContainer using message listener and connection factory and channel topic as:

1
2
3
4
5
6
7
8
9
10
@Bean
    RedisMessageListenerContainer redisMessageListenerContainer() {
        final RedisMessageListenerContainer container =
                        new RedisMessageListenerContainer();
        container.setConnectionFactory( getConnectionFactory() );
        container.addMessageListener( messageListenerAdapter(), createTopic() );
        return container;
    }

Now our message publisher and subscriber is ready to test. Let us add some code to test our pubSub messaging mechanism:

1
2
3
4
5
6
IRedisPublisher redisPublisher = context.getBean(IRedisPublisher.class);
        //Now publish a simple string message
        redisPublisher.publish("Hello Omanand");
        redisPublisher.publish("How are you?");
        redisPublisher.publish("Are you receiving my message?");

If you test program, you will notice two issues here. First, the process will never complete as the listener is always waiting for the new messages on the channel. The second issue you may notice that some junk character will appear in the message subscriber on receiving the message. As the message is a byte[] and the value deserializer we have configured for redisTemplate is StringRedisSerializer. For shutting down the container add following code in your App.java:

1
2
3
//Get the message listener container and shutdown the listener now.
        RedisMessageListenerContainer container = context.getBean(RedisMessageListenerContainer.class);
        container.stop();

Change the StringRedisSerializer to GenericToStringSerializer for fixing the other issue of getting junk character in the subscriber.

1
redisTemplate.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));

This concludes our basic demo application for the redis publish/subscribe messaging system. As promised in the previous post, following section will describe the basic configuration for enabling replication of redis data store.

Configure Redis Replication in 2 minute
The master-slave replication setup for redis is quite trivial. Please following steps to setup the replication:

 

  • Copy your redis.conf file in the redis home directory as redis_slave.conf
    $ cp redis.conf redis_slave.conf

  • Open redis_slave.conf and change the line “port 6379” to “port 6380”.
  • Edit redis_slave.conf to change the line “dbfilename dump.rdb” to “dbfilename dump_slave.rdb”.
  • Add following line in the redis_slave.conf: “slaveof 127.0.0.1 6379”.

 

That’s it. Now run your slave server instance using the following command
./src/redis-server redis_slave.conf

Now your master-slave replication is ready. Try to query slave instance with some existing key to validate the results.

You can download the complete source code for this series at my git repository.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *