Redis Pub/Sub with Spring Data Redis:消息以错误的顺序到达
Redis Pub/Sub with Spring Data Redis: Messages arrive in wrong order
我正在尝试使用 Redis publish/subscribe 和 Spring Data 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 同步 send/receive 消息?
当前的代码库很小,可以在 GitHub.
查看
Redis PubSub 以按顺序传递消息而著称(至少在使用一个连接并触发 PUBLISH
时保证)。PUBLISH
命令 returns 发送的客户端数量通知)。乱序的原因是 Spring Data Redis 默认发送消息的方式。通知在不同的线程上处理,这就是原因。感谢代码,它帮助我快速重现了行为。
我可以想到两种可能的策略来解决这个问题:
但是,您可以提供一个在 RedisMessageListenerContainer
内执行订单的执行者。现在,我想到的任何形式的同步都会损害性能。
在 BinaryJedisPubSub
之上实现自己的消息侦听器。您可以控制消息,并且可以忽略执行程序问题。
HTH,马克
我正在尝试使用 Redis publish/subscribe 和 Spring Data 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 同步 send/receive 消息?
当前的代码库很小,可以在 GitHub.
查看Redis PubSub 以按顺序传递消息而著称(至少在使用一个连接并触发 PUBLISH
时保证)。PUBLISH
命令 returns 发送的客户端数量通知)。乱序的原因是 Spring Data Redis 默认发送消息的方式。通知在不同的线程上处理,这就是原因。感谢代码,它帮助我快速重现了行为。
我可以想到两种可能的策略来解决这个问题:
但是,您可以提供一个在
RedisMessageListenerContainer
内执行订单的执行者。现在,我想到的任何形式的同步都会损害性能。在
BinaryJedisPubSub
之上实现自己的消息侦听器。您可以控制消息,并且可以忽略执行程序问题。
HTH,马克