Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subscribe command doesn't work as expected #1341

Closed
varelasavela opened this issue Jul 7, 2016 · 13 comments
Closed

subscribe command doesn't work as expected #1341

varelasavela opened this issue Jul 7, 2016 · 13 comments

Comments

@varelasavela
Copy link

varelasavela commented Jul 7, 2016

Expected behavior

  1. When I am trying to do this :
Thread t = new Thread(() -> {

            jedisCluster.subscribe(keyExpiredListener, "__keyevent@0__:expired");
        });
 t.start();

The implementation of jedisCluster is to pick random node and subscribe only to that node. So if the key is located on that node, it will work, but if it is located on other node , it will not work.

I tried to do the following:

   final Map<String, JedisPool> nodesPool = jedisCluster.getClusterNodes();
        for (Map.Entry<String, JedisPool> entry : nodesPool.entrySet()) {
            try (Jedis jedis = entry.getValue().getResource()) {
               if (jedis.info("Replication").contains("role:master")){
                    Thread t = new Thread(() -> {
                        jedis.subscribe(new KeyExpiredListener(), "__keyevent@0__:expired");
                    });
                    t.start();
                }
     } catch (Exception e) {
                System.out.println(e.getMessage());
            }

I got this error after few seconds of working well:
redis.clients.jedis.exceptions.JedisException: Unknown message type: [B@37a326c7
at redis.clients.jedis.JedisPubSub.process(JedisPubSub.java:149)
at redis.clients.jedis.JedisPubSub.proceed(JedisPubSub.java:102)
at com.vp.configuration.KeyExpiredListener.proceed(KeyExpiredListener.java:32)
at redis.clients.jedis.Jedis.subscribe(Jedis.java:2628)
at java.lang.Thread.run(Thread.java:745)

Redis / Jedis Configuration

notify-keyspace-events : Ex

Jedis version:

2.8.1

Redis version:

3.2.1

Java version:

8

@AnatolyTikhonov
Copy link

I encountered the same problem also for psubscribe.
Any suggestions how to solve it?

@NimrodTicotzner
Copy link

Critical issue for me as well

@marcosnils
Copy link
Contributor

@varelasavela according to redis cluster spec clients can subscribe to any node and RedisCluster should forward notifications across the cluster

http://redis.io/topics/cluster-spec#publishsubscribe.

have you tried if this works outside Jedis?

@varelasavela
Copy link
Author

@marcosnils yes, I tried. Pub/sub works as described iin the spec in redis-cli and Jedis as well, but psubscribe works different. In redis-cli you should subscribe in each node to the pattern in order to catch the event. When I tried to do the same in Jedis, I got the event but after few seconds got exception which I copied to the body of my question

@xetorthio
Copy link
Contributor

It seems like psubscribe should work as subscribe in a cluster. I guess we should ask @antirez

@marcosnils
Copy link
Contributor

marcosnils commented Jul 8, 2016

@xetorthio IIUC @varelasavela has problems with subscribe as well.

@marcosnils
Copy link
Contributor

marcosnils commented Jul 8, 2016

@varelasavela this works for me

        final JedisCluster jc = new JedisCluster(new HostAndPort("localhost", 30001));

        new Thread(new Runnable() {
            @Override
            public void run() {
                jc.subscribe(new JedisPubSub() {
                    @Override
                    public void onMessage(String channel, String message) {
                        System.out.println(channel + " " + message);
                    }

                    @Override
                    public void onSubscribe(String channel, int subscribedChannels) {
                        System.out.println("Subscribed");
                    }
                }, "__keyevent@0__:expired");
            }
        }).start();


        for (int i = 0; i < 10000; i++) {
            jc.publish("__keyevent@0__:expired", "test" + i);
        }

Is there a way to consistently reproduce the error you're getting?

@marcosnils
Copy link
Contributor

marcosnils commented Jul 8, 2016

@varelasavela BTW psubscribe also works.

        final JedisCluster jc = new JedisCluster(new HostAndPort("localhost", 30001));

        new Thread(new Runnable() {
            @Override
            public void run() {
                jc.psubscribe(new JedisPubSub() {
                    @Override
                    public void onPSubscribe(String pattern, int subscribedChannels) {
                        System.out.println("Subscribed");
                    }

                    @Override
                    public void onPMessage(String pattern, String channel, String message) {
                        System.out.println(pattern + channel + message);
                    }
                }, "*pepe*");
            }
        }).start();


        for (int i = 0; i < 10000; i++) {
            jc.publish("pepe"+i, "test" + i);
        }

@varelasavela
Copy link
Author

varelasavela commented Jul 8, 2016

@marcosnils
yes, do the following:

           final JedisCluster jc = new JedisCluster(new HostAndPort("localhost", 30001));

        new Thread(new Runnable() {
            @Override
            public void run() {
                jc.subscribe(new JedisPubSub() {
                    @Override
                    public void onMessage(String channel, String message) {
                        System.out.println(channel + " " + message);
                    }

                    @Override
                    public void onSubscribe(String channel, int subscribedChannels) {
                        System.out.println("Subscribed");
                    }
                }, "__keyevent@0__:expired");
            }
        }).start();

now, go to redis-cli
find some key to being redirect to port 30002 or other master
lets assume it "key1", run setex key1 5 5.
I catch the event only if key1 located on 30001.

@marcosnils
Copy link
Contributor

@varelasavela I don't understand why setex should trigger a onMessage ? The only operation that you'll get is a publish <channel> <message> y any of the cluster nodes.

Can you please describe the exactly steps to reproduce the issue?. Even though I used your snippet I still get notifications when I publish keys in any node.

@varelasavela
Copy link
Author

@marcosnils I will explain.
We are talking about notify-keyspace-events feature of Redis. When the key is expired, Redis is sending event to channel "keyevent@0:expired". But as I understand, this event is published only in specific node where the key is located.
To reproduce it do exactly that I described in previous comment. You don't need to publish event, just run setex on specific key and Redis will publish it by itself.
But turn on notify-keyspace-events feature before by : CONFIG SET notify-keyspace-events xE

@marcosnils
Copy link
Contributor

@varelasavela got it. I missed the part where you were talking about keyspace notifications.

This has been reported as a redis issue as well. I'm waiting for @antirez or someone from redis to reply here: redis/redis#3022 so we know how this should be addressed

@sazzad16
Copy link
Collaborator

Closing due to redis/redis-doc#1367
Reference: redis/redis#3022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants