Skip to content

MQTT Durable Sessions

EMQXにはDurable Sessions機能があり、MQTTセッションとメッセージをディスクに永続的に保存し、高可用性のレプリカを提供してデータの冗長性と整合性を確保します。セッションの耐久性により、効果的なフェイルオーバーとリカバリー機構を実装でき、サービスの継続性と可用性を保証し、システムの信頼性を向上させます。

本ページでは、EMQXにおけるセッション永続化の概念、原理、および利用方法を紹介します。

基本概念

EMQXのDurable Sessions機能を理解する前に、EMQXに関するいくつかの基本概念を押さえておくことが重要です。

セッションと耐久ストレージ

セッション:セッションは、EMQX内でクライアント接続ごとに作成される軽量なプロセスです。セッションはMQTT標準で定められたブローカーの動作を実装しており、初回接続、トピックのサブスクライブ・サブスクライブ解除、メッセージの配信などを行います。

耐久ストレージ(Durable Storage, DS):耐久ストレージはEMQX内部のデータベースです。セッションは自らの状態やトピックに送信されたMQTTメッセージを保存するために利用します。耐久ストレージのデータベースエンジンはRocksDBを用いてデータをディスクに保存し、Raftアルゴリズムを使ってクラスター内でデータを一貫して複製します。耐久ストレージとDurable Sessionsは混同しないように注意してください。

セッション有効期限(Session Expiry Interval)

MQTT標準によれば、クライアントセッションはMQTTブローカー内でクライアント接続と状態を管理します。**有効期限(Expiry Interval)**は、クライアント接続が終了した後にブローカーがセッション状態を保持する期間を制御するセッションのプロパティです。本ドキュメントではこのプロパティが重要な役割を果たします。

有効期限が0に設定されたセッションは、クライアントがEMQXに接続している間のみ存在します。クライアントが切断されると、サブスクリプションや未配信メッセージを含むすべてのセッション情報は即座に破棄されます。一方、有効期限が0以外のセッションは、クライアント接続が終了した後もEMQXに保持されます。クライアントがセッション有効期限内に再接続すれば、セッションを再開でき、オフライン時に送信されたメッセージも配信されます。

  • MQTT 5プロトコルを使用するクライアントは、CONNECTまたはDISCONNECTパケットのSession Expiry Intervalプロパティで明示的にセッション有効期限を指定できます。

  • MQTT 3.*プロトコルを使用するクライアントの場合、EMQXは以下のルールでセッション有効期限を決定します。Clean Sessionフラグがtrueなら有効期限は0に設定され、それ以外の場合はmqtt.session_expiry_interval設定パラメータの値が使用されます。

EMQXにおけるセッション実装

EMQXは用途に応じて最適化された2種類のクライアントセッション実装を提供しています。

  • レギュラーセッション:実行中のEMQXノードのメモリ上に状態を保持するセッション。ノード再起動時に状態は失われます。
  • Durable Sessions:状態と受信メッセージを耐久ストレージにバックアップするセッション。EMQXノード再起動後も再開可能です。

セッション実装の選択はセッション有効期限とdurable_sessions.enable設定パラメータ(グローバルまたはゾーン単位で設定可能)によって決まります。選択基準は以下の通りです。

durable_sessions.enableセッション有効期限 = 0セッション有効期限 > 0
falseレギュラーレギュラー
trueレギュラーDurable Sessions

EMQXはメッセージ耐久性を管理する独自のアプローチを採用しており、レギュラーセッションとDurable Sessionsが共存しつつストレージコストを最小化しています。

セッション実装の比較

クライアントセッションの管理戦略はサービスの安定性と信頼性を確保する上で重要です。本節では2つのセッション実装の特徴を比較し、それぞれの特性と適用シナリオを理解しやすくし、より適切なデプロイ判断を支援します。

レギュラーセッション

この実装はデフォルトであり、EMQX 5.7以前のすべてのリリースで使用されてきました。レギュラーセッションの状態は実行中のEMQXノードのRAMに完全に保持されます。

利点:

  • 非常に高いスループットと低レイテンシ。
  • クライアントへの即時メッセージ配信。

欠点:

  • セッションデータはホストノードが停止または再起動すると失われる。
  • 未配信メッセージはセッションのメモリキューに保存され、EMQXのメモリ使用量が増加する。
  • メモリ枯渇を防ぐため、EMQXはメモリキューのサイズ制限を設けている。制限を超えると新規メッセージは破棄され、未配信メッセージが失われる可能性がある。

Durable Sessions

EMQX v5.7.0で導入されたDurable Sessionsは、セッション状態とDurable Sessionsにルーティングされるメッセージをディスクに保存します。この機能はデフォルトで無効であり、durable_sessions.enabletrueに設定することで有効化できます。

Durable Sessionがトピックフィルターをサブスクライブすると、そのフィルターにマッチするトピックは「耐久性あり」とマークされます。これにより、これらのトピックからレギュラーセッションへのMQTT PUBLISHメッセージのルーティングに加え、ブローカーはメッセージをmessagesという耐久ストレージにも保存します。

メッセージ配信プロトコルはパブリッシャーではなくサブスクライバーのセッションの耐久性に依存する点に注意が必要です。

各Durable MQTTメッセージは、サブスクライブするDurable Sessionsの数や接続状態に関わらず、各レプリカに対して一度だけ保存されます。これにより効率的なメッセージファンアウトとディスク書き込みの最小化が実現します。

耐久ストレージは、EMQXクラスター内の複数ノードにセッションメタデータとMQTTメッセージを一貫して複製することで、高い耐久性と高可用性を提供します。設定可能なレプリケーションファクターにより、メッセージやセッションのレプリカ数を調整でき、耐久性とパフォーマンスのバランスを利用者の要件に合わせてカスタマイズ可能です。

利点:

  • EMQXノードの再起動や停止後もセッションを再開可能。
  • MQTTメッセージはメモリキューではなく共有かつ複製された耐久ストレージに保存されるため、オンライン・オフラインセッション双方のRAM使用量を削減。
  • 未配信メッセージ数に上限がなく、メモリキューのオーバーフローによるメッセージ破棄が発生しない。

欠点:

  • メッセージをディスクに保存するため、システム全体のスループットは低下する。
  • Durable Sessionsはレギュラーセッションに比べてレイテンシが高い。メッセージの書き込みと読み込みがバッチ処理されるため、スループットは向上するが、クライアントがパブリッシュメッセージを受信するまでの遅延が増加する。

Durable Sessionsのクイックスタート

本節では、EMQXおよびMQTTクライアントでDurable Sessions機能を素早く利用する方法と、Durable Sessionsの簡単なワークフローを紹介します。

注意

Durable Sessionsを有効にしていなくても、ステップ2〜4を実行するとセッションは保持され、メッセージはクライアントキューに保存されます。違いは、ステップ5でノード再起動後にセッションが永続的に保存されるかどうか、復元可能かどうかです。

  1. EMQXでDurable Sessions機能を有効化します。

    デフォルトではDurable Sessionsは無効です。etc/emqx.confファイルを編集し、以下の設定を追加して機能を有効にします。

    bash
    durable_sessions {
      enable = true
    }

    設定変更後、EMQXを再起動して反映させます。

  2. MQTTクライアントの接続パラメータを調整し、セッション耐久性を有効にします。

    例としてMQTTX CLI(デフォルトでMQTT 5.0を使用)を用います。--no-cleanオプションでClean Start = falseを設定し、クライアントIDをemqx_cに指定してEMQXに接続し、t/1トピックをサブスクライブします。

    bash
    mqttx sub -t t/1 -i emqx_c --no-clean -q 1
  3. クライアントを切断し、セッションが保持されていることを確認します。

    ステップ2のクライアントを切断します。EMQXダッシュボードのモニタリング -> クライアントページを開くと、クライアントの状態がDisconnectedのまま表示され、セッションが保持されていることがわかります。

    MQTT persistent session

  4. クライアントにメッセージを送信し、メッセージがクライアントキューに保存されることを確認します。

    再度MQTTX CLIを使い、benchコマンドで1クライアントからt/1トピックに繰り返しメッセージをパブリッシュします。

    bash
    mqttx bench pub -t t/1 -c 1 -q 1

    MQTTプロトコルに従い、emqx_cクライアントがオフラインでも、サブスクライブしているt/1トピックのメッセージはクライアントキューに保存され、再接続時に配信されます。

  5. EMQXノードを再起動し、セッションとメッセージが耐久ストレージから復元されることを確認します。

    EMQXノードを再起動します。クライアント接続操作を行わずにEMQXダッシュボードのモニタリング -> クライアントページを開くと、クライアントがDisconnected状態で表示され、セッションが復元されていることがわかります。

    同じクライアントID emqx_c--no-clean オプション(Clean Start = false)を指定してEMQXに再接続します。

    bash
    mqttx sub -t t/1 -i emqx_c --no-clean -q 1

    オフライン期間中に受信したメッセージが現在のクライアントに配信されます。

    bash
    ...
    [2024-5-22] [16:14:14] › …  Connecting...
    [2024-5-22] [16:14:14] › ✔  Connected
    [2024-5-22] [16:14:14] › …  Subscribing to t/1...
    [2024-5-22] [16:14:14] › ✔  Subscribed to t/1
    [2024-5-22] [16:14:14] › payload: Hello From MQTTX CLI
    ...

    注意

    • 永続セッションを復元するには、同じクライアントID emqx_c を使用し、--no-cleanオプションでClean Startfalseに設定する必要があります。この2つの条件を満たす必要があります。
    • 以前のサブスクリプション情報はセッションに保存されているため、再接続時にt/1トピックを再度サブスクライブしなくてもメッセージは配信されます。

耐久ストレージのアーキテクチャ

Durable Sessionsはセッション状態とメッセージの永続化に耐久ストレージを利用します。このストレージ層の構造と動作については、Design for Durable StorageArchitecture: Backends and Storage Hierarchyセクションを参照してください。

耐久ストレージがDurable Sessionsおよび共有サブスクリプションセッションを支える仕組み

耐久ストレージはEMQXのDurable Sessionsおよび共有サブスクリプションセッションの基盤です。

Durable Sessions

Durable SessionsはDSデータベースエンジン上に実装されています。クライアントが非ゼロのセッション有効期限で接続すると、EMQXはセッション状態をDSに保存します。

  • メッセージ永続化:

    Durable SessionがQoS > 0のトピックフィルターをサブスクライブすると、そのフィルターはEMQXのルーティングテーブルで「耐久性あり」とマークされます。これにより、そのトピックにパブリッシュされたメッセージは通常のクライアントへの配信に加え、DSにも保存されます。

  • 進捗管理:

    Durable Sessionsはイテレーターという軽量マーカーを用いてDSからメッセージを読み取ります。イテレーターは各耐久ストレージストリーム内の進捗を追跡し、切断やノード再起動後も確実にメッセージ再生を再開可能にします。

  • 効率的なストレージ:

    メッセージはDSの各レプリカに対して一度だけ保存されます。複数のDurable Sessionsが同じトピックをサブスクライブしていても、ストレージオーバーヘッドは最小化されます。

共有サブスクリプションセッション

EMQX v6.0以降、DSは共有サブスクリプションセッションの永続化もサポートしています。共有サブスクリプションはDSを利用してサブスクライバーグループ内で一貫したメッセージ分配を維持します。

  • イテレーター管理:

    指定された共有サブスクリプションリーダーがグループのイテレーターセットを管理し、メンバーにイテレーターを割り当てて協調的な消費を実現します。

  • 再生とリバランス:

    共有トピックをサブスクライブするセッションはリーダーと通信し、メッセージ再生のためのイテレーターを借用します。更新されたイテレーターはリーダーに報告されます。クライアント切断やグループのリバランス時にはリーダーがイテレーターを取り上げ、他のメンバーに再配布して消費の継続性と負荷分散を保証します。

これらの仕組みにより、サブスクリプショングループ全体でのロードバランシング、メッセージ順序維持、フォールトトレランスが実現されます。

クラスター全体の耐久ストレージ

EMQXクラスター内の各ノードには一意のサイトIDが割り当てられます。これはErlangノード名(emqx@...)に依存しない安定した識別子で、ノードの初回起動時にランダム生成され永続化されます。この安定性により、ノード名変更や再設定があってもデータの整合性が保たれます。

管理者はemqx_ctl ds info CLIコマンドを使ってクラスター内の各サイトの耐久ストレージ状況を管理・監視できます。

Durable Sessionsのハードウェア要件

セッション耐久性を有効にすると、EMQXはDurable SessionsのメタデータとDurable Sessionsに送信されたMQTTメッセージをディスクに保存します。そのため、十分なストレージ容量を持つサーバーにEMQXをデプロイする必要があります。EMQXのデータディレクトリはローカルファイルシステムを使用しなければなりません。なぜなら組み込みの耐久ストレージバックエンドはNFSやSMB/CIFSなどのネットワークファイルシステムをサポートしていないためです。最高のスループットを得るにはSSDストレージの利用を推奨します。

ディスク容量の目安は以下の通りです。

  • メッセージストレージ:各レプリカで必要なメッセージ保存容量は、受信メッセージレートにdurable_sessions.message_retention_periodパラメータで指定された保持期間を乗じた値に比例します。このパラメータはメッセージ保持期間を決定し、総ストレージ容量に影響します。
  • セッションメタデータストレージ:セッションメタデータの容量は、セッション数に各セッションがサブスクライブするストリーム数を乗じた値に比例します。
  • ストリーム数の計算:ストリーム数はシャード数に比例し、トピック数にも(非線形に)依存します。EMQXは構造が類似したトピックを自動的に同一ストリームにまとめるため、トピック数の増加に対してストリーム数の増加は抑制され、セッションごとのメタデータ量を最小化します。

次のステップ

Durable Sessions機能の設定・管理方法や、EMQXクラスターでのDurable Sessionsの初期設定および変更方法については、以下のページを参照してください。

さらに詳しく

MQTT Durable Sessionsの設計原理についてより深く理解したい場合は、Design for Durable Storageをご覧ください。