使用Jedis实现Redis键过期通知

18

我正在尝试使用Redis实现过期键通知,即当我的键在Redis数据存储中过期时。 Redis网站提供了一些描述如何使用http://redis.io/topics/notifications,但我无法找到任何使用Redis Java客户端(如Jedis)的示例?

如果有可能提供带有说明的代码将非常有帮助,因为我对Redis还不熟悉。

2个回答

40

只有使用发布-订阅模式才能做到。

启动Redis服务器。

将redis.conf中的notify-keyspace-events更改为KEA(根据您的要求)。有关详细信息,请参阅Redis文档 http://redis.io/topics/notifications

Redis Java客户端(Jedis),请尝试以下操作:

通知监听器:

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


}

订阅者:

****注意** jedis.psubscribe(new KeyExpiredListener(), "__key*__:*"); -- 此方法支持基于正则表达式模式的频道 而 jedis.subscribe(new KeyExpiredListener(), ""__keyspace@0__:notify"); --此方法需要完整/精确的频道名称

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*__:*");

    }

}

测试类:

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);

    }
}

现在首先启动你的订阅者,然后运行TestJedis。你将看到以下输出:

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

现在有一种用例,您也对已过期的键的感兴趣。

注意:Redis仅通过keyspace事件的通知在键到期时提供键,一旦键过期,值就会丢失。 为了在键过期时获得值,您可以使用如下所示的变通方法来创建一个特殊的“阴影”键的概念:

当您创建通知键时,请同时创建一个特殊的过期“阴影”键(不要使实际通知过期)。例如:

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

// 在频道 keyevent@0 中获取到一个过期消息: // 将键按“:”(或你决定使用的任何分隔符)分割,在第二部分中获取原始键

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

请注意,阴影密钥的值不会被使用,因此您需要使用可能是空字符串""的最小可能值。这需要进行一些额外的设置工作,但上述系统正好符合您的需求。额外开销包括一些额外的命令来实际检索和删除您的密钥以及一个空密钥的存储成本。

否则,您必须以包含附加值的方式准备密钥。

希望对您有所帮助!


1
太好了!你真的节省了我很多时间,伙计。我整天都在寻找这个。感谢 @Kuntal-G 提供的代码和适当的说明。 - Rocky Ray
onPMessage 中有没有获取 "umq" 值的方法? - Kaidul
请检查更新后的答案,以获取键过期时的值。 - Kuntal-G
如何先运行一个类? - Don Corleone

-4

这可能会对你有所帮助。

        JedisPool jedisPool=null;
        JedisPoolConfig poolConfig = null;

        try {

            poolConfig=new JedisPoolConfig();
            jedisPool = new JedisPool(poolConfig,"127.0.0.1" /*Host IP*/,1234 /*Port*/, 0);             
            Jedis jedis=jedisPool.getResource();            
            jedis.expire("KeyName", 10 /*Key Expires in 10 seconds*/);  

        } catch (Exception e) {

        }

1
根据我的理解,用户正在询问如何在密钥过期时获得通知,而不是像您在代码中展示的那样使密钥过期。 - Kuntal-G
@Vishvesh,感谢您的回复。但是Kuntal是正确的,我知道过期时间,但我正在寻找Redis文档中提到的键过期通知机制。 - Rocky Ray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接