JedisDataException: ERR only (P)SUBSCRIBE/(P)UNSUBSCRIBE/QUIT allowed in thi


詳細
最近redisの配布/購読をして、問題のような悩みが長い間現れて、ネット上でも関連する解答はめったにありません.今日やっと解決したので、ここで過程を記録します.
 
まず、パブリッシュクラス:
 
public class Publisher {
	public void publish(final Jedis jedis) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("       :");
//				String channel = jedis.get("channel");
//				String message = jedis.get("300C00");
//				System.out.println("[  ]:" + channel + "," + message);
				try {
				     Thread.currentThread().sleep(2000);
				    } catch (InterruptedException e) {
				     e.printStackTrace();
				}
//jedis.publish(String channel, String message)
				jedis.publish("D00C003", "oklalllla");
                                jedis.publish("hello", "oklalllla");
			}
		}).start();;
	}
}

 
 
クラスの購読:
 
public class Subscriber1 {
	public void sub(final Jedis jedis, final MyListener1 listener) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("     ……");
//subscribe(JedisPubSub, String[] channels) psubscribe(JedisPubSub, String[] patterns)
				jedis.subscribe(listener, new String[]{"300C00", "news.share"});
			}  
		}).start();
	}
}

 
サブスクリプション・クラスは、パブリケーション・メッセージを受信した後の処理を示すリスニング・クラスに依存します.JeidsPubSubベースクラスを継承する必要があります.
public class MyListener1 extends JedisPubSub {
	
	//          
	@Override
	public void onMessage(String channel, String message) {
		System.out.print("onMessage:          	");
		System.out.println(channel + "=" + message);  
	}
	
	//                  
	@Override
	public void onPMessage(String pattern, String channel, String message) {
		System.out.print("onPMessage:                      ");
		System.out.println(pattern + "=" + channel + "=" + message);
	}
	
	//                 
	@Override
	public void onPSubscribe(String pattern, int subscribedChannels) {
		System.out.print("onPSubscribe:                    ");
		System.out.println(pattern + "=" + subscribedChannels);  
	}
	
	//                 
	@Override
	public void onPUnsubscribe(String pattern, int subscribedChannels) {
		System.out.print("onPUnsubscribe:                    ");
		System.out.println(pattern + "=" + subscribedChannels); 
	}
	
	//          
	@Override
	public void onSubscribe(String channel, int subscribedChannels) {
		System.out.print("onSubscribe:             ");
		System.out.println(channel + "=" + subscribedChannels); 
	}
	
	//         
	@Override
	public void onUnsubscribe(String channel, int subscribedChannels) {
		System.out.print("onUnsubscribe:            ");
		System.out.println(channel + "=" + subscribedChannels);
	}

}

 
次はテストです.
//  Jedis
		Jedis jedis1 = JedisFactory.getJedis();
		Jedis jedis2 = JedisFactory.getJedis();
		MyListener2 listener = new MyListener2();
		 //    channel message
		 Publisher2 publisher = new Publisher2();
		 publisher.publish(jedis2);
		 //  
		 Subscriber1 scribe = new Subscriber1();
		 scribe.sub(jedis1, listener);

 
JedisFactory:
public class JedisFactory {
	private static Jedis jedis;
	static {
		 //       
        JedisPoolConfig config = new JedisPoolConfig(); 
        config.setMaxIdle(5); 
        config.setMaxWaitMillis(1000l); 
        config.setTestOnBorrow(false); 
        // slave   
//        List shards = new ArrayList(); 
//        shards.add(new JedisShardInfo("127.0.0.1", 6379, "master")); 

        //     
       JedisPool pool = new JedisPool(config,"127.0.0.1",6379, 100000); //       
       jedis = pool.getResource();
	}
	
	public static Jedis getJedis() {
		return jedis;
	}
}

 
実行後、問題に示す異常が発生しました.
redis.clients.jedis.exceptions.JedisDataException: ERR only (P)SUBSCRIBE/(P)UNSUBSCRIBE/QUIT allowed in this context
at redis.clients.jedis.Protocol.processError(Protocol.java:104)
at redis.clients.jedis.Protocol.process(Protocol.java:122)
at redis.clients.jedis.Protocol.read(Protocol.java:191)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:175)
at redis.clients.jedis.Jedis.set(Jedis.java:54)
 
この異常の表面的な意味は、Jedisのパブリケーションとサブスクリプションデータに異常が発生し、指定された状況だけがコンテキストにあるということです.よくわかりませんが、下層APIを調べてみると、配布、購読の文法が間違っていないことがわかり、N久に悩まされました!!!
自分が書いたJeidsFactoryに問題があることに気づいた.JedisFactoryと書く本意はJedisオブジェクトを取得するコードをカプセル化することであるが,知らず知らずのうちにgetJedis()メソッドは,パブリケーションとサブスクリプションがそれぞれこのメソッドを呼び出したにもかかわらず,永遠に同じJedisオブジェクトを取得する単例である.だから新聞が間違っている......(なぜ発行、購読が同じJedisを使えないのか、私も原因が分かりません..)
変更:
 
static JedisPool pool;
	static {
		 //       
        JedisPoolConfig config = new JedisPoolConfig(); 
        config.setMaxIdle(5); 
        config.setMaxWaitMillis(1000l);  
        config.setTestOnBorrow(false); 
        // slave   
//        List shards = new ArrayList(); 
//        shards.add(new JedisShardInfo("127.0.0.1", 6379, "master")); 

        //     
       pool = new JedisPool(config,"127.0.0.1",6379, 100000); //       
      
	}

 
パブリッシュとサブスクリプションをpoolから取得すると、次のようになります.
 
Jedis jedis1 = pool.getResource();
Jedis jedis2 = pool.getResource();

 
実行順序:
配信メッセージ->購読メッセージ->on(P)Subscibe->on(P)Message(psubscribeで購読する場合はonPSubscribe、onPMessage)
 
だから、自分がこの問題を抱えていることに気づいて、サブスクリプションを発行する文法が間違っていないことに気づいたら、問題がここにあるかどうかを見ることができます.--パブリッシュ、サブスクリプションは異なるredisクライアントを使用します!