MQTT Durable Sessions
EMQXにはDurable Sessions機能があり、MQTTセッションとメッセージをディスクに永続的に保存することで、高可用性のレプリカを提供し、データの冗長性と一貫性を確保します。セッションの耐久性により、効果的なフェイルオーバーとリカバリ機構を実装でき、サービスの継続性と可用性を保証し、システムの信頼性を向上させます。
本ページでは、EMQXにおけるセッション永続化の概念、原理、および利用方法を紹介します。
基本概念
EMQXのDurable Sessions機能を理解する前に、EMQXに関するいくつかの基本概念を把握することが重要です。
セッションとDurable Storage
セッション:セッションは、EMQX内でクライアント接続ごとに作成される軽量なプロセスです。セッションはMQTT標準で規定されたブローカーの動作を実装しており、初期接続、トピックのサブスクライブ・サブスクライブ解除、メッセージの配信などを行います。
Durable Storage(DS):Durable StorageはEMQX内部のデータベースです。セッションはこのストレージを利用して状態やトピックに送信されたMQTTメッセージを保存します。Durable StorageのデータベースエンジンはRocksDBを用いてデータをディスクに保存し、Raftアルゴリズムによりクラスター内でデータの一貫したレプリケーションを行います。Durable Storageと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:状態と受信メッセージをDurable Storageにバックアップするセッション。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.enableをtrueに設定することで有効化できます。
Durable Sessionsがトピックフィルターをサブスクライブすると、EMQXはそのフィルターにマッチするトピックを「Durable」とマークします。これにより、これらのトピックからのMQTT PUBLISHメッセージはレギュラーセッションにルーティングされるだけでなく、messagesと呼ばれるDurable Storageにも保存されます。
メッセージ配信のプロトコルは、パブリッシャーではなくサブスクライバーのセッションの耐久性に依存することに注意が必要です。
各Durable MQTTメッセージは、サブスクライブするDurable Sessionsの数や接続状態に関わらず、各レプリカに1回だけ保存されます。これにより効率的なメッセージのファンアウトとディスク書き込みの最小化が実現されます。
Durable Storageは、EMQXクラスター内の複数ノードにセッションメタデータとMQTTメッセージを一貫してレプリケートすることで、高い耐久性と高可用性を提供します。設定可能なレプリケーションファクターにより、メッセージやセッションのレプリカ数を調整でき、耐久性とパフォーマンスのバランスをカスタマイズ可能です。
Durable Sessionsの利点:
- EMQXノードの再起動や停止後もセッションを再開可能。
- MQTTメッセージは共有かつレプリケートされたDurable Storageに保存され、メモリキューの使用を削減。
- 未配信メッセージ数に上限がなく、メモリキューのオーバーフローによるメッセージ破棄が発生しない。
一方、欠点もあります:
- メッセージをディスクに保存するため、全体的なスループットは低下する。
- Durable Sessionsはバッチ処理でメッセージの書き込み・読み込みを行うため、レギュラーセッションよりレイテンシが高い。バッチ処理はスループット向上に寄与するが、クライアントがメッセージを受信するまでの遅延(エンドツーエンドレイテンシ)を増加させる。
Durable Sessionsのクイックスタート
本節では、EMQXおよびMQTTクライアントでDurable Sessions機能を素早く利用する方法と、Durable Sessionsの簡単なワークフローを紹介します。
注意
Durable Sessionsが有効でなくても、ステップ2~4の操作はセッションを保持し、メッセージはクライアントキューに保存されます。違いは、ステップ5でノード再起動後にセッションが永続的に保存されているか、復元可能かどうかです。
EMQXでDurable Sessions機能を有効化します。
デフォルトではDurable Sessionsは無効です。
etc/emqx.confファイルを編集し、以下の設定を追加して機能を有効化してください。bashdurable_sessions { enable = true }設定反映のためEMQXを再起動します。
MQTTクライアントの接続パラメータを調整し、セッション耐久性を有効にします。
例としてMQTTX CLIを使用します。デフォルトでMQTT 5.0プロトコルを使用するため、
--no-cleanオプションを付けてClean Start = falseを設定し、クライアントIDをemqx_cに指定してEMQXに接続し、t/1トピックをサブスクライブします。bashmqttx sub -t t/1 -i emqx_c --no-clean -q 1クライアントを切断し、セッションを保持します。
ステップ2のクライアントを切断します。EMQXダッシュボードのMonitoring -> Clientsページを開くと、クライアントの状態がDisconnectedのままで、セッションが保持されていることが確認できます。

クライアントにメッセージを送信し、メッセージがクライアントキューに保存されることを確認します。
再度MQTTX CLIを使用し、
benchコマンドで1クライアントからt/1トピックに繰り返しメッセージをパブリッシュします。bashmqttx bench pub -t t/1 -c 1 -q 1MQTTプロトコルに従い、
emqx_cクライアントがオフラインでも、サブスクライブしているt/1トピックのメッセージはクライアントキューに保存され、再接続時に配信されます。EMQXノードを再起動し、Durable Storageからセッションとメッセージが復元されます。
EMQXノードを再起動します。クライアント接続操作を行わずにEMQXダッシュボードのMonitoring -> Clientsページを開くと、クライアントがDisconnected状態で表示され、セッションが復元されていることがわかります。
同じクライアントID
emqx_cと--no-cleanオプションを指定してClean Start = falseでEMQXに接続してみてください。bashmqttx 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 Startをfalseに設定する必要があります。 - 以前のサブスクリプション情報はセッションに保存されているため、再接続時に
t/1トピックを再サブスクライブしなくてもメッセージは配信されます。
- 永続セッションを復元するには、同じクライアントID
Durable Storageのアーキテクチャ
Durable Sessionsはセッション状態とメッセージの永続化にDurable Storageを利用しています。このストレージ層の構造と動作については、Design for Durable Storageの「Architecture: Backends and Storage Hierarchy」セクションを参照してください。
Durable StorageがDurable SessionsおよびShared Subscription Sessionsを支える仕組み
Durable StorageはEMQXのDurable SessionsおよびShared Subscription Sessionsの基盤です。
Durable Sessions
Durable SessionsはDSデータベースエンジン上に実装されています。クライアントが非ゼロのセッション有効期限で接続すると、EMQXはセッション状態をDSに保存します。
メッセージ永続化:
Durable SessionsがQoS > 0のトピックフィルターをサブスクライブすると、そのトピックフィルターはEMQXのルーティングテーブルで「Durable」とマークされます。これにより、そのトピックにパブリッシュされたメッセージはレギュラークライアントへの配信に加え、DSにも保存されます。
進捗管理:
Durable SessionsはDSのイテレータを使ってメッセージを読みます。イテレータは各Durable Storageストリーム内でセッションの進捗を軽量に追跡するマーカーであり、切断やノード再起動後もメッセージ再生を確実に再開可能にします。
効率的なストレージ:
メッセージは、トピックをサブスクライブするDurable Sessionsの数に関わらず、DSの各レプリカに1回だけ保存され、ストレージオーバーヘッドを最小化します。
Shared Subscription Sessions
EMQX v6.0以降、DSはShared Subscription Sessionsの永続化もサポートしています。Shared SubscriptionはDSを利用してサブスクライバーグループ間で一貫したメッセージ分配を維持します。
イテレータ管理:
指定されたShared Subscriptionリーダーがグループのイテレータセットを管理し、メンバーにイテレータを割り当てて協調的な消費を保証します。
再生とリバランス:
Sharedトピックをサブスクライブするセッションはリーダーと通信し、メッセージ再生用のイテレータを借用します。更新されたイテレータはリーダーに報告されます。クライアント切断やグループリバランス時には、リーダーがイテレータを取り消し、他のメンバーに再配布して消費の継続性と負荷分散を確保します。
これらの仕組みにより、サブスクライバーグループ全体での負荷分散、メッセージ順序、フォールトトレランスが実現されます。
クラスター全体のDurable Storage
EMQXクラスター内の各ノードには一意のSite IDが割り当てられており、Erlangノード名(emqx@...)に依存しない安定した識別子として機能します。Site IDはノードの初回起動時にランダム生成され永続化されます。この安定性により、ノード名の変更や再設定があってもデータの整合性が維持されます。
管理者はemqx_ctl ds info CLIコマンドを使用して、クラスター内の各サイトのDurable Storageの状態を管理・監視できます。
Durable Sessionsのハードウェア要件
セッション耐久性を有効にすると、EMQXはDurable SessionsのメタデータとDurable Sessionsに送信されたMQTTメッセージをディスクに保存します。そのため、十分なストレージ容量を持つサーバーにEMQXをデプロイする必要があります。最高のスループットを得るには、SSDストレージの使用を推奨します。
ディスク容量の目安は以下の通りです。
- メッセージストレージ:各レプリカに保存されるメッセージの容量は、受信メッセージレートに
durable_sessions.message_retention_periodパラメータで指定された保持期間を掛けた値に比例します。このパラメータはメッセージ保持期間を制御し、必要な総ストレージ量に影響します。 - セッションメタデータストレージ:セッションメタデータの容量は、セッション数に各セッションがサブスクライブしているストリーム数を掛けた値に比例します。
- ストリーム数の計算:ストリーム数はシャード数に比例し、トピック数にも(非線形に)依存します。EMQXは構造が類似したトピックを同一ストリームに自動統合し、トピック数の増加に伴うストリーム数の急激な増加を抑制し、セッションあたりのメタデータ容量を最小化します。
次のステップ
Durable Sessions機能の設定・管理方法や、EMQXクラスターでのDurable Sessionsの初期設定および変更方法については、以下のページを参照してください。
さらに詳しく
MQTT Durable Sessionsの設計原理についてより深く理解したい場合は、Design for Durable Storageを参照してください。