javaredisjgroups

redis onExpire event handled by only one instance


I have 2 instances of an application running in cluster(JGroups) and having a listener registered on the onExpire event of redis, the issue is that the listener is triggered by the 2 instances. How can I make it handled only by one instance?


Solution

  • I've figured out how to solve the problem with creating a new cache for locking the execution of onExpired for only one instance. In the event execution implementation I am checking whether the instance could execute it or no like bellow

    class InvalidationListener implements CacheEntryExpiredListener<String, .....> {
    
        .....
    
        @Override
        public void onExpired(Iterable<CacheEntryEvent<? extends String, ? extends ....>> events) {
    
            events.forEach(event -> {
                try {
                    ....
                    boolean canExecute = cacheLock.putIfAbsent(key, InetAddress.getLocalHost().getHostAddress());
                    if (canExecute) {
                        logger.info("This instance will execute the onExpired ");
                        ....
                    } else {
                        logger.info("onExpired already executed by another instance");
                    }
                } catch (IOException e) {
                    logger.error("An error occured in onExpired event", e);
                }
            });
    
        }
    }
    

    Explanation : The first instance to run the onExpired will set the locking entry to true and execute the expiration implementation and then any other instance will not change the value (putIfAbsent) as it's already true and then it will return false and it will never duplicate the expiration implementation execution. The locking entry key is the same as the expired key and the value is the instance's IP Address just for future traceability in Redis.

    PS: Each cacheLock entry will be expired after 15 seconds to release memory in Redis.