0Pricing
RabbitMQ Messaging & Async Systems · レッスン

メッセージの確認応答と永続性

手動の確認応答を実装し、メッセージとキューを永続化して、メッセージの信頼性を確保します。Consumer や Broker の障害時にもデータが失われないようにします。

「メッセージの確認応答と永続性」はCoddyKit上の無料RabbitMQ Messaging & Async Systemsレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはRabbitMQ Messaging & Async Systems学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 RabbitMQ Messaging & Async Systemsコースには全4レッスンが含まれています。

このレッスンの一部はまだ翻訳されておらず、英語で表示されています。

Introduction to Reliability

In distributed systems, ensuring messages are processed reliably is paramount. What happens if a server crashes? Or if a message consumer fails mid-processing?

This lesson explores two key mechanisms in RabbitMQ to prevent data loss and ensure reliability: Message Acknowledgements and Durability for both messages and queues.

What are Message Acknowledgements?

When a consumer receives a message, it needs to tell RabbitMQ that it has successfully processed it. This confirmation is called an Acknowledgement (or 'ack').

  • Without Acks: If a consumer crashes before processing, the message is lost.
  • With Acks: If a consumer crashes, RabbitMQ knows the message wasn't acknowledged and can redeliver it to another consumer.

Automatic vs. Manual Acknowledgements

RabbitMQ supports two modes for acknowledgements:

  • Automatic (Auto-ack): RabbitMQ considers a message acknowledged as soon as it's delivered to the consumer. This is simple but risky, as messages can be lost if the consumer crashes immediately after receiving but before processing.
  • Manual (Explicit Ack): The consumer explicitly sends an acknowledgement back to RabbitMQ *after* it has successfully processed the message. This is the recommended approach for reliable processing.

Implementing Manual Acknowledgements

Let's see how to implement manual acknowledgements in a Java consumer. We use channel.basicAck() after our message processing logic completes.

Try running this example. The consumer will acknowledge the message after a short delay.

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class ConsumerAck {
    private final static String QUEUE_NAME = "ack_queue";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        // Declare a non-durable queue
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        // Set prefetch count to 1 for fair dispatch (covered in Work Queues)
        channel.basicQos(1);

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
            try {
                Thread.sleep(1000); // Simulate work
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
            System.out.println(" [x] Done and Acknowledged");
        };
        
        // false means manual acknowledgement
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {});

        // Producer to send a message (for testing)
        Channel producerChannel = connection.createChannel();
        producerChannel.queueDeclare(QUEUE_NAME, false, false, false, null);
        producerChannel.basicPublish("", QUEUE_NAME, null, "Hello Ack!".getBytes("UTF-8"));
        System.out.println(" [x] Sent 'Hello Ack!'");
    }
}

Handling Failed Message Processing

What if a consumer fails to process a message? Instead of acknowledging it, you can negatively acknowledge it:

  • channel.basicNack(deliveryTag, multiple, requeue): Rejects one or more messages.
  • channel.basicReject(deliveryTag, requeue): Rejects a single message.

The requeue parameter is crucial. If true, the message is sent back to the queue for another consumer. If false, it's discarded or sent to a Dead Letter Exchange (DLX), which we'll cover in a later lesson.

What is Message Durability?

Acknowledgements handle consumer failures, but what about the RabbitMQ broker itself? If the server crashes or restarts, what happens to messages in the queues?

Message Durability ensures that messages persist on disk and survive a broker restart. This means critical messages are never lost, even if the RabbitMQ server goes down unexpectedly.

Making Messages Persistent

To make a message durable, you need to mark it as 'persistent' when publishing. This tells RabbitMQ to write the message to disk.

We use MessageProperties.PERSISTENT_TEXT_PLAIN for this.

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

public class ProducerPersistent {
    private final static String QUEUE_NAME = "persistent_queue";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            
            // Declare a durable queue first!
            channel.queueDeclare(QUEUE_NAME, true, false, false, null);
            
            String message = "Hello Persistent Message!";
            channel.basicPublish(
                "", 
                QUEUE_NAME, 
                MessageProperties.PERSISTENT_TEXT_PLAIN, // Mark message as persistent
                message.getBytes("UTF-8")
            );
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}

What is Queue Durability?

Just like messages, queues themselves can be durable. If a queue is not durable, it will be lost if the RabbitMQ broker restarts. Any messages inside it (even persistent ones!) will also be lost.

Therefore, for true reliability, both the queue and the messages within it must be durable.

Declaring a Durable Queue

To make a queue durable, you simply set the durable parameter to true when declaring it. This must be done by both the producer and consumer when they declare the queue.

Run this example. It declares a durable queue and sends a persistent message.

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

public class ProducerDurable {
    private final static String DURABLE_QUEUE = "my_durable_queue";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            
            // Declare a durable queue (durable = true)
            channel.queueDeclare(
                DURABLE_QUEUE, 
                true,  // durable
                false, // exclusive
                false, // autoDelete
                null   // arguments
            );
            
            String message = "Hello from a durable queue!";
            channel.basicPublish(
                "", 
                DURABLE_QUEUE, 
                MessageProperties.PERSISTENT_TEXT_PLAIN, // Persistent message
                message.getBytes("UTF-8")
            );
            System.out.println(" [x] Sent '" + message + "' to durable queue.");
        }
    }
}

Quick Check on Reliability

To ensure maximum message reliability (messages are not lost even if a consumer or broker fails), which combination of features is generally required?

Recap & Next Steps

You've learned how to make your RabbitMQ messaging more reliable!

  • Manual Acknowledgements confirm message processing, preventing loss on consumer failure.
  • Message Durability (persistent messages) ensures messages survive broker restarts.
  • Queue Durability ensures the queue definition itself survives broker restarts.

By combining these, you can build robust systems where messages are rarely lost. Next, you'll explore advanced routing patterns using different types of exchanges!

よくある質問

「メッセージの確認応答と永続性」レッスンは無料ですか?

はい。「メッセージの確認応答と永続性」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、RabbitMQ Messaging & Async Systemsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 RabbitMQ Messaging & Async Systemsコースには全4レッスンが含まれています。

「メッセージの確認応答と永続性」で何を学びますか?

手動の確認応答を実装し、メッセージとキューを永続化して、メッセージの信頼性を確保します。Consumer や Broker の障害時にもデータが失われないようにします。 ブラウザで直接実行するハンズオンコードでRabbitMQ Messaging & Async Systemsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

RabbitMQ Messaging & Async Systemsを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのRabbitMQ Messaging & Async Systemsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「メッセージの確認応答と永続性」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このRabbitMQ Messaging & Async Systemsレッスンでコードを書いて実行できますか?

はい。すべてのRabbitMQ Messaging & Async Systemsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Hello World:シンプルなキュー
  2. Work Queues:公平なディスパッチ
  3. メッセージの確認応答と永続性
  4. Fanout ExchangeによるPublish/Subscribe
← RabbitMQ Messaging & Async Systemsに戻る