Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expired key trigger event - Spring data Redis

I am trying to setup a Key expiry event handler using spring data redis but am not able to make it work. I did some research but dint yeild expected results. Not sure what i am missing. I would like to LOG a message when the key on the redis cache expires.

@Configuration
@EnableRedisRepositories
public class RedisConfig {

    @Bean 
    StringRedisTemplate stringRedisTemplate(){
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(jedisConnectionFactory());
        return stringRedisTemplate;
    }

    @Bean
    RedisMessageListenerContainer redisContainer() {
        RedisMessageListenerContainer container 
          = new RedisMessageListenerContainer(); 
        container.setConnectionFactory(jedisConnectionFactory()); 
        container.addMessageListener(messageListener(), topic()); 
        return container; 
    }

    @Bean
    MessageListenerAdapter messageListener() { 
        return new MessageListenerAdapter(new RedisMessageSubscriber());
    }

    @Bean
    MessagePublisher redisPublisher() { 
        return new RedisMessagePublisher();
    }

    @Bean
    ChannelTopic topic() {
        return new ChannelTopic("messageQueue");
    }
}


public interface MessagePublisher {
    void publish(String message);
}

public class RedisMessagePublisher implements MessagePublisher {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ChannelTopic topic;

    public void publish(String message) {
        stringRedisTemplate.convertAndSend(topic.getTopic(), message);
    }
}

@Service
public class RedisMessageSubscriber implements MessageListener {

    private static final Logger LOG = Logger.getLogger(RedisMessageSubscriber.class);

    public static List<String> messageList = new ArrayList<String>();

    @Override
    public void onMessage(Message message, byte[] pattern) {
        messageList.add(message.toString());
    }

}

Can someone help? Thanks

like image 864
tindu edward Avatar asked Mar 29 '18 19:03

tindu edward


1 Answers

At first, need to enable keyspace notification for expire event in redis. By default keyspace events notifications are disabled because while not very sensible the feature uses some CPU power. Notifications are enabled using the notify-keyspace-events of redis.conf or via the CONFIG SET.

notify-keyspace-events "Ex"

When you are done with redis, you need to configure your message listener with a pattern topic "__keyevent@*__:expired". Here goes the code sample.

Listener Class:

@Component
public class ExpirationListener implements MessageListener {
    private static final Logger logger = LoggerFactory.getLogger(ExpirationListener.class);

    @Override
    public void onMessage(Message message, byte[] bytes) {
        String key = new String(message.getBody());
        logger.debug("expired key: {}", key);
    }
}

Configuration:

@Bean
RedisMessageListenerContainer keyExpirationListenerContainer(RedisConnectionFactory connectionFactory, ExpirationListener expirationListener) {
    RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
    listenerContainer.setConnectionFactory(connectionFactory);
    listenerContainer.addMessageListener(expirationListener, new PatternTopic("__keyevent@*__:expired"));
    listenerContainer.setErrorHandler(e -> logger.error("There was an error in redis key expiration listener container", e));
    return listenerContainer;
}
like image 77
Monzurul Shimul Avatar answered Oct 19 '22 11:10

Monzurul Shimul