Rocky Ray Rocky Ray - 16 days ago 4
Java Question

Redis Key expire notification with Jedis

I am trying to implement a expiry key notification with redis ,when my key expires in the redis data store. The redis website provides some description of how http://redis.io/topics/notifications, but Im unable to find any example how to do it using redis java client like Jedis?

Any possible code with illustration will be very helpful as im new to redis.

Answer

You can do it with the pub-sub model only Start Redis Server

Change the notify-keyspace-events in redis.conf to KEA (this depends on your requirement).Details given in redis documentation http://redis.io/topics/notifications.

Redis Java Client (Jedis) ,Try the following:

Notification Listener:

public class KeyExpiredListener extends JedisPubSub {

@Override
    public void onPSubscribe(String pattern, int subscribedChannels) {
        System.out.println("onPSubscribe "
                + pattern + " " + subscribedChannels);
    }

@Override
    public void onPMessage(String pattern, String channel, String message) {

        System.out
                .println("onPMessage pattern "
                        + pattern + " " + channel + " " + message);
    }

//add other Unimplemented methods


}

Subscriber:

****Note** jedis.psubscribe(new KeyExpiredListener(), "key*:*"); -- This methos support regex pattern based channel whereas jedis.subscribe(new KeyExpiredListener(), ""keyspace@0:notify"); --This method takes full/exact channel name

public class Subscriber {

    public static void main(String[] args) {
        JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");

        Jedis jedis = pool.getResource();
        jedis.psubscribe(new KeyExpiredListener(), "__key*__:*");

    }

}

Test Class:

public class TestJedis {

    public static void main(String[] args) {
        JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");

        Jedis jedis = pool.getResource();
        jedis.set("notify", "umq");
        jedis.expire("notify", 10);

    }
}

Now first start your Subscriber and then Run the TestJedis.You wil see the following output:

onPSubscribe __key*__:* 1
onPMessage pattern __key*__:* __keyspace@0__:notify set
onPMessage pattern __key*__:* __keyevent@0__:set notify
onPMessage pattern __key*__:* __keyspace@0__:notify expire
onPMessage pattern __key*__:* __keyevent@0__:expire notify
onPMessage pattern __key*__:* __keyspace@0__:notify expired
onPMessage pattern __key*__:* __keyevent@0__:expired notify

Now one use-case where you are interested in the value of the expired key as well.

Note: Redis only provide the key on expiration of key through notification of keyspace events, value is lost once the key expire. In-order to get the value on your key expire you can do the following work around shown below with the tricky concept of shadow key:

When you create your notify key, also create a special expiring "shadow" key (don't expire the actual notify). For example:

// set your key value
SET notify umq 
//set your "shadow" key, note the value here is irrelevant
SET shadowkey:notify "" EX 10 

// Get an expiration message in the channel keyevent@0:expired // Split the key on ":"(or whatever separator you decide to use), take the second part to get your original key

// Then get the value and do whatever with it
GET notify
// Then delete the key
DEL notify

Note that the value of the shadowkey isn't used so you want to use the smallest possible value, could be an empty string "". It's a little more work to setup but the above system does exactly what you need. The overhead is a few extra commands to actually retrieve and delete your key plus the storage cost of an empty key.

Otherwise you have to prepare your key in such a way that it includes the value appended with it.

Hope it helps you!