Jira Data Center のキャッシュ レプリケーション

Jira Data Center 7.9 以降でのキャッシュ レプリケーションは非同期で行われます。つまり、キャッシュ レプリケーションは、発生後すぐには他のノードにレプリケートされず、ローカル キューに追加されます。その後、キュー内での順序に基づいてバックグラウンドでレプリケートされます。 

このアプローチは、以下を実現できるようサポートします。

  • クラスターの拡張性の向上
  • ノード間でのキャッシュ量の不一致を軽減
  • レプリケーションとキャッシュ変更を分け、プロセス全体を簡素化して迅速化

キャッシュ変更のレプリケーション

ローカル キュー

キャッシュ変更をキューに追加する前に、各ノードでローカル キューを作成する必要があります。変更が適切にグループ化され、順序化されるよう、各ノードには個別のキューが作成されます。

キューは自動的に作成されます。クラスターにノードを追加するたびに、残りのノードがそれを検出し、ファイル システム上にキューを作成します。ノードは次のクエリを使用して、クラスター全体についての情報をデータベースから取得します。

select node_id, node_state from clusternode


このクエリの出力は次のようになります (ポート番号や IP アドレスなどの詳細も含まれます)。

node_idnode_state
Node 1ACTIVE
Node 2ACTIVE
Node 3ACTIVE
Node 4OFFLINE


active 状態の各ノードに対し、それぞれのノードはファイル システム上に 10 個の個別キューを作成します。アトラシアンではスループットを増加させるために、キューの数を 10 としています。これは、多数のアクションを完了させる必要があるため、1 件の変更の複製を高速化することはできませんが、同時に 10 件の変更を複製できるためです。

Node 1Node 2、および Node 3 の 3 ノード クラスターでは、次のキューが作成されます。

Node 1:

  • 変更を Node 2 に複製する 10 個のキュー
  • 変更を Node 3 に複製する 10 個のキュー

Node 2:

  • 変更を Node 1 に複製する 10 個のキュー
  • 変更を Node 3 に複製する 10 個のキュー

Node 3:

  • 変更を Node 1 に複製する 10 個のキュー
  • 変更を Node 2 に複製する 10 個のキュー


ファイル システムでの見え方

キューは、各ノードの <local-home-directory>/localq ディレクトリで作成されます。このディレクトリのコンテンツは次のようになります。

Node 1 の /localq ディレクトリ
queue_Node2_0_f5f366263dcc357e2720042f33286f8f
..
queue_Node2_9_f5f366263dcc357e2720042f33286f8f
queue_Node3_0_bbb747b1516b5225f1ec1c65887b39fc
..
queue_Node3_9_bbb747b1516b5225f1ec1c65887b39fc 


キューが作成されると、キャッシュ変更をキューに追加する準備が整います。クラスターにノードを追加するたびに、このノード用にさらに 10 のキューが既存の各ノード上で作成されます。新しいノードは、すべてのアクティブな既存ノードのキューを作成します。

キャッシュ変更をローカル キューに追加する

すべてのキューが配置されると、特定のノードで発生する各キャッシュ イベントが適切なキューに追加されます。

例として、Node 1 を使用してみましょう。

Node 1:

  1. キャッシュ イベントが発生します (権限スキームへの変更など)。
  2. 変更はデータベース内で行われ、この変更に関するローカル キャッシュは削除されます。
  3. キャッシュを削除するリクエストが次のローカル キューに追加され、そこから適切なノードにレプリケートされます。
    • queue_Node2 (Node 2 の場合)
    • queue_Node3 (Node 3 の場合)。

1 つのスレッド内で発生した変更は、常に同じキューに追加されます。これは、1 つのスレッド内の 2 つのイベントが互いに依存している場合に、それらのレプリケーション順序を維持するためです。

キャッシュ変更をローカル ノードから他のノードにレプリケートする

キャッシュの変更がローカル キューに追加されると、それらは別のスレッドによって処理されます。各キューには、次の処理を行うスレッド 1 つあります。

  • キューからキャッシュ変更リクエストを読み込む。
  • RMI を介して、キャッシュ変更リクエストを宛先ノードに配信する。
  • キューからキャッシュ変更リクエストを削除する。


Node 1 の queue_Node2 および queue_Node3 にキャッシュ変更が追加された同じ例を使用すると、この変更での以降の手順は次のようになります。

  • キューに追加された変更を処理するスレッドは、ローカル キュー queue_Node2 から変更を読み込み、RMI を介して Node 2 に配信しようとします。
  • キューに追加された変更を処理する別のスレッドは、ローカル キュー queue_Node3 から変更を読み込み、RMI を介して Node 3 に配信しようとします。

変更が正常にレプリケートされると、そのキューから削除されます。レプリケーションに失敗すると、ログにエラーが書き込まれます。

キャッシュ レプリケーションの監視

ログ ファイルに書き込まれた統計のレビューを行うことで、キャッシュ レプリケーションを監視できます。ログ ファイルでは、ローカル キューのサイズ、キャッシュ変更が正常にレプリケートされたかどうか、またはキュー内に長時間残っているかどうかなどを確認できます。ほとんどの場合、いくつかのパラメーターを監視するだけで、レプリケーションが正常に動作しているかどうかがわかります。

詳細については、「キャッシュ レプリケーションの監視」を参照して下さい。

キャッシュ レプリケーションの構成

キャッシュ レプリケーションでは、キュー内の変更の最大数や、統計の保存頻度など、いくつかのオプションを設定できます。

これらはシステム プロパティであることにご注意ください。 


構成オプションを表示...
オプション既定値説明
jira.cache.replication.localq.time.sync.tolerance.millis900 000 (15 分)

ノード間の時刻同期許容値を設定します (ミリ秒)。


jira.cache.replication.localq.queue.max.size100 000

単一のローカル キューにおけるキャッシュ変更の最大数を指定します。

Jira 8.16 から非推奨になりました。代わりに com.atlassian.jira.stats.logging.interval を使用してください。
jira.cache.replication.localq.queue.stats.logging.interval.seconds

n

スナップショット統計の保存頻度 (秒単位) を変更します。

詳細情報

キャッシュ レプリケーションについて詳しく理解するには、以下のセクションを展開してください。


キャッシュの変更をスキップ...

キューがすでに最大サイズ (既定では 100,000 件の変更) に到達している場合、キャッシュの変更はローカル キューに追加されません。レプリケーションが正常に動作していれば、キャッシュの変更はレプリケートされた後ただちにキューから削除されるため、この問題は発生しないはずです。

キューに変更が加えられていない場合は、ログ ファイル内の次のエントリで確認できます。

Not enough space left for persisting localQCacheOp, usableSpaceInBytes: {}, estimateObjectSizeInBytes: {}. Skipping replication of this cache event.

また、キューの既定のサイズを増やすこともできます。上記の「キャッシュ レプリケーションの構成」を参照してください。

キャッシュの変更をシリアル化...

キャッシュの変更リクエストはキューに追加される前にシリアル化 (バイトに変換) され、キューから読み取られるときには逆シリアル化されます。アトラシアンでは標準的な Java シリアル化を使用しており、RMI を介してリクエストを送信するときにも同じメカニズムを使用します。

回復可能なエラー...

回復可能なエラーは一般的に、ノードが短期間オフラインになる、またはレプリケーションを停止するネットワークの問題などの、一時的な問題です。根本となっている問題が解決すると、このような状況が解消されます。この場合、レプリケーションが再開し、遅延した変更を配信します。 

これらのエラーは、ログ ファイル内の次のエントリで確認できます。 

Checked exception: {exception name} occurred when processing: {cache replication request} from cache replication queue: {queue name}, failuresCount: {}. Will retry indefinitely.

また、統計情報の sendCheckedExceptionCounter パラメータを確認することで、発生した回復可能なエラーの数を確認することもできます。

回復不能なエラー...

回復不能なエラーにより、キャッシュの変更がいくつか失われる可能性があります。これらは通常、キャッシュ変更リクエスト自体によって発生します。これらのリクエストの例として、プラグインの不足や Jira バージョンが異なるなどの理由により、宛先ノードが変更を逆シリアル化できない場合があります。

キャッシュのレプリケーションを継続させるため、レプリケーションに数回失敗し、他のノードに配信できなかった場合、これらの変更はスキップされます。

これらのエラーは、ログ ファイル内の次のエントリで確認できます。

Runtime exception: {exception-name} occurred when processing: {cache-replication-message} from cache replication queue: {queue-name}, failuresCount: {}/{}, error: {exception}
Abandoning sending: {cache-replication-message} from cache replication queue: {queue-name}, failuresCount: {}/{}. Removing from queue. Error: {exception}"

また、統計情報の sendRuntimeExceptionCounter パラメータを確認することで、発生した回復不能なエラーの数を確認することもできます。

これらの問題が解消されない場合...

これにより、クラスターが同期されないことがあります。この問題を解決するため、キャッシュをクリアして、最初から再構築することができまます。これを行うには、ノードを 1 つずつシャットダウンしてから、もう一度再起動します。ノードはデータベースからすべての値を読み込み、新しいキャッシュの構築を開始します。

RMI 経由でリクエストを送信...

レプリケーションを高速化するため、Ehcache の CachePeer (別ノード上のキャッシュを表すオブジェクト) もキャッシュします。このため、キャッシュの変更が必要になるたびに作成する必要はなく、代わりにすべての変更のキャッシュされたバージョンを再使用します。

リモート RMI レジストリで CachePeer を検索する際、コネクションの詳細はデータベースの clusternode テーブルから取得されます。これらは正確なため、コネクションは機能します。ただし、キャッシュされたバージョンを通じて後から複製した場合、コネクションの詳細がリモート ノードによって設定され、ホスト名とポート番号の両方が異なる場合があります。この場合は変更を複製できません。

これらのエラーは、ログ ファイル内の次のエントリで確認できます。

Cache {cache-name} requested bootstrap but a CacheException occured.
java.rmi.ConnectIOException: Exception creating connection to: {destination_hostname}

この問題を解決するには、各ノードにアクセスし、次のプロパティに接続の詳細を入力します。

システム プロパティ

java.rmi.server.hostname

Cluster.properties ファイル

ehcache.object.port

最終更新日: 2021 年 1 月 15 日

この内容はお役に立ちましたか?

はい
いいえ
この記事についてのフィードバックを送信する

このセクションの項目

Powered by Confluence and Scroll Viewport.