5

Spring Data Redis で Redis のパブリッシュ/サブスクライブを使用してチャットを実装しようとしています。

以下に示すように、RedisTemplate を使用してメッセージを公開します。

public class RedisPublisher {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void publish(ChannelTopic channelTopic, Object channelMessage) {
        redisTemplate.convertAndSend(channelTopic.getTopic(), channelMessage);
    }
}

そして、メッセージを受信するために、以下に示すように MessageListener があります。

public class RedisConsumer implements MessageListener {

MessageSerializer serializer = new MessageSerializer();
AtomicInteger atomicInteger = new AtomicInteger(0);

@Override
public void onMessage(Message message, byte[] pattern) {

    Object obj = serializer.deserialize(message.getBody());
    if(obj != null && obj instanceof RedisMessage) {
        System.err.println("Received message(" + atomicInteger.incrementAndGet() + ") " + obj.toString());
    }

}

メッセージは次のように発行されます。

final ChannelTopic channelTopic=connectionManager.subscribe("topic");
    new Thread(new Runnable() {
        public void run() {                
            Thread.sleep(5000);                
            for (int i = 0; i < 10; i++) {
                redisPublisher.publish(channelTopic, new RedisMessage(i + 1));
            }
        }
    }).run();

ただし、受信したメッセージは間違った順序で配信されているようです。

Received message(1) message id: 3
Received message(2) message id: 2
Received message(3) message id: 1
Received message(4) message id: 4
Received message(5) message id: 5
Received message(6) message id: 6
Received message(7) message id: 7
Received message(8) message id: 8
Received message(9) message id: 9
Received message(10) message id: 10

Springが提供するRedisTemplate/MessageListenerを使ってメッセージを同期的に送受信することは可能ですか?

現在のコードベースは小さく、 GitHubで表示できます。

4

1 に答える 1

6

Redis PubSub は、メッセージを順番に配信することが知られています (少なくとも 1 つの接続とトリガーを使用する場合は保証されますPUBLISHPUBLISHコマンドは、通知されたクライアントの数を返します)。順不同の原因は、Spring Data Redis がデフォルトでメッセージをディスパッチする方法です。通知は異なるスレッドで処理されます。それが理由です。コードをありがとう、動作をすばやく再現するのに役立ちました。

この問題に対処するには、次の 2 つの戦略が考えられます。

  1. ただし、 内の順序を尊重するエグゼキュータを指定できますRedisMessageListenerContainer。現在、私が考えているどのような形式の同期も、パフォーマンスに悪影響を及ぼします。

  2. 上に独自のメッセージ リスナーを実装しますBinaryJedisPubSub。あなたはメッセージを管理しており、executor の問題を省略できます。

HTH、マーク

于 2015-08-26T18:55:41.943 に答える