四种主流消息队列(Kafka、ActiveMQ、RabbitMQ、RocketMQ)的生产者与消费者传递信息的机制说明,以及实际使用中的注意事项和示例:
poll
方式)并处理。Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer producer = new KafkaProducer<>(props);
producer.send(new ProducerRecord<>("my-topic", "key", "message"));
producer.close();
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "my-group");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));
while (true) {
ConsumerRecords records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord record : records) {
System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
}
}
key
)。acks=all
确保消息写入所有副本后返回成功,但会增加延迟。ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue("my-queue");
MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage("Hello ActiveMQ!");
producer.send(message);
connection.close();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
Queue queue = session.createQueue("my-queue");
MessageConsumer consumer = session.createConsumer(queue);
TextMessage message = (TextMessage) consumer.receive();
System.out.println("Received: " + message.getText());
consumer.acknowledge(); // 手动确认消息
connection.close();
DeliveryMode.PERSISTENT
,否则消息可能丢失。deadLetterExchange
和 deadLetterRoutingKey
处理无法消费的消息。ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection()) {
Channel channel = connection.createChannel();
String exchangeName = "direct-exchange";
channel.exchangeDeclare(exchangeName, "direct");
String routingKey = "user.login";
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.contentType("text/plain")
.deliveryMode(2) // 持久化
.build();
channel.basicPublish(exchangeName, routingKey, props, "Login Event".getBytes());
}
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection()) {
Channel channel = connection.createChannel();
String queueName = "user_queue";
channel.queueDeclare(queueName, true, false, false, null);
String exchangeName = "direct-exchange";
channel.queueBind(queueName, exchangeName, "user.login");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("Received: " + message);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume(queueName, false, deliverCallback, consumerTag -> {});
}
ACK
确认消息处理,避免重复消费。channel.basicAck()
或 channel.basicNack()
。x-dead-letter-exchange
和 x-dead-letter-routing-key
。vm_memory_high_watermark
。DefaultMQProducer producer = new DefaultMQProducer("my-group");
producer.setNamesrvAddr("localhost:9876");
producer.start();
Message msg = new Message("my-topic", "Order-123".getBytes(), "JSON".getBytes());
SendResult sendResult = producer.send(msg);
System.out.println("Send Result: " + sendResult);
producer.shutdown();
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my-group");
consumer.setNamesrvAddr("localhost:9876");
consumer.subscribe("my-topic", "*"); // 订阅所有队列
consumer.registerMessageListener(new MessageListener() {
@Override
public void consume(Message msg, ConsumeContext context) throws Exception {
System.out.println("Received: " + new String(msg.getBody()));
context.commitMessage(msg); // 提交消费位移
}
});
consumer.start();
MessageQueueSelector
,确保同一订单的所有消息进入同一队列。特性 | Kafka | ActiveMQ | RabbitMQ | RocketMQ |
---|---|---|---|---|
模型 | 发布-订阅(仅 Topic) | 支持点对点和发布-订阅 | 灵活路由(多种交换器) | 主题+队列(顺序/广播) |
持久化 | 支持分区副本 | 支持消息持久化和事务 | 支持队列和消息持久化 | 支持消息持久化和事务 |
顺序性 | 单分区有序 | 不保证(除非事务) | 可通过队列保证 | 单队列严格有序 |
适用场景 | 高吞吐、日志/事件流 | 通用、企业级消息系统 | 复杂路由、多协议支持 | 高可靠、顺序消息、分布式事务 |
URL: 浅识MQ的 Kafka、ActiveMQ、RabbitMQ、RocketMQ区别-CSDN博客
URL:浅聊MQ之Kafka、RabbitMQ、ActiveMQ、RocketMQ持久化策略-CSDN博客
(望各位潘安、各位子健/各位彦祖、于晏不吝赐教!多多指正!)