仮想インスタンスのデータベースパーティショニング
データベースパーティショニングにより、各 Liferay DXP 仮想インスタンスに独自のデータベーススキーマが割り当てられ、すべてのインスタンスが 1 つのスキーマを共有し、行が companyId 列で区切られるデフォルトの単一スキーマレイアウトが置き換えられます。 その結果、テナントの分離が強化され、大規模テーブルに対するクエリが高速化され、インスタンスごとにバックアップとデータ所在地の制御が可能になった。 (Liferay DXPでは「仮想インスタンス」と「会社」は同じ意味で使用されます。基となるデータベース識別子は companyIdです。)
データベースパーティショニングは、Liferayのセルフホスト型デプロイメントとLiferayのPaaSデプロイメントの両方に適用されます。 Liferay SaaSでは、仮想インスタンスの設定はLiferayによって管理されます。
パーティショニングには主に4つの利点があります。
-
クエリのパフォーマンス: 大きなテーブルは会社ごとに分割されているため、データベースはクエリ、インデックスの再構築、またはその他のメンテナンス操作中に不要なレコードをスキャンしたりフィルタリングしたりしません。
-
より強力なデータ分離: 各インスタンスのデータは独自のスキーマに存在します。 権限チェックを回避するコードパス(企業間における 安全でない直接オブジェクト参照 (IDOR) 漏洩の典型的な原因)であっても、現在のリクエストに属するパーティションにしか到達できません。
-
データ所在地の制御: スキーマごとのストレージにより、各テナントのデータがどこにあるかを明示的に制御できるため、GDPR やその他の現在または将来のデータ所在地に関する法律への準拠が簡素化されます。
-
メンテナンスが簡素化: バックアップ、移行、エクスポート/インポートは単一の仮想インスタンスに限定できるため、すべてのテナントのデータを含む共有スキーマに対して操作するよりも高速でリスクが低くなります。
前提条件
パーティショニングを有効にする前に、インストールが以下の要件を満たしていることを確認してください。
-
データベースはMySQLまたはPostgreSQLです。
-
設定されたデータベースユーザーは、Liferay DXPが作成するすべてのスキーマに対して、データ定義言語(DDL)の権限を持っています。 スキーマ名は
[prefix][companyId]のパターンに従います (デフォルトのプレフィックスはlpartition_)。Liferay DXP は、仮想インスタンスを追加するたびに新しいスキーマを作成します。
データベースのパーティショニングは元に戻すことができません。 パーティション分割されたインストール環境を単一スキーマ構成に戻すためのサポートされている手順はありません。 有効化する前にデータベースの完全バックアップを取得し、それに応じて展開計画を立ててください。 パーティショニングはMySQLとPostgreSQLでのみサポートされています。
データベースパーティショニングの有効化
新しい Liferay DXP インストールでデータベースパーティショニングを有効にするには、サーバーを初めて起動する前に、次のプロパティを portal-ext.properties に追加してください。
database.partition.enabled=true
サーバーがパーティショニングを有効にして起動した後、デフォルトの会社のスキーマは、JDBC/JNDI接続からの名前を引き続き使用します(例: lportal)。 新しい仮想インスタンスはすべて、設定されたプレフィックスパターンに従って専用のスキーマを作成します。 デフォルトのプレフィックスと会社 ID 20001の場合、スキーマは lpartition_20001 です。
インストール環境に既に複数の仮想インスタンスが存在する場合、プロパティだけでは不十分です。 既存のデータは単一のスキーマに格納されているため、まず企業ごとのスキーマに分割する必要があります。 プロパティを有効にする前に、 仮想インスタンス移行ツール を使用して既存のインスタンスをそれぞれ抽出し、パーティションとして再挿入します。
スキーマプレフィックスのカスタマイズ
各新しいスキーマは、 [prefix][companyId] のパターンに従います。 デフォルトのプレフィックスは lpartition_ です。 別のプレフィックスを使用するには、 portal-ext.properties でこのプロパティを設定します。
database.partition.schema.name.prefix=myprefix_
接頭辞の最大長は11文字です。 Liferay DXPは、現在のプレフィックス値と会社IDを連結することでパーティションスキーマを解決するため、パーティションスキーマが既に存在する場合にプレフィックスを変更する場合は、サーバーを再起動する前に、それらのスキーマの名前を新しいプレフィックスを使用するように変更してください。
マルチスレッドを無効にする
Liferay DXPはデフォルトで、企業を反復処理する操作(アップグレード、検証プロセス、インデックスの再生成など)を並列化するため、独立したパーティションは同時に処理されます。 並列処理がデータベースまたはアプリケーションサーバーに問題を引き起こしている場合にのみ、並列処理を無効にしてください。
database.partition.thread.pool.enabled=false
設定ファイルの制限事項
OSGi 設定ファイル (.config ファイル ( Liferay Home内) は、次の 4 つのスコープで動作します: SYSTEM、 COMPANY、 GROUP、および ポートレットインスタンス。 パーティショニングが有効になっている場合、 PORTLET_INSTANCE スコープの構成ファイルは即座に拒否されます。 GROUP スコープ付き構成ファイルは、対象会社も識別する場合( companyId プロパティまたは groupKey が 1 に解決される場合)にのみ受け入れられます。 ポートレットインスタンスのスコープ設定は、UI または構成ヘッドレス API を使用して構成してください。
デフォルト会社をメンテナンス用に予約する
デフォルトの会社(Liferay DXPが最初にインストールされたときに作成された会社)は、テナント間の制御テーブルをホストし、他のインスタンスを管理するためのエントリポイントとなります。 テナント間管理(新規インスタンスの作成、アップグレードの実行、メンテナンスの実施など)専用とし、顧客コンテンツをそこにホストすることは避けてください。
パーティショニングの仕組み
Liferay DXP は、現在の companyId に一致するスキーマにすべての SQL 操作をルーティングします。 あなたの視点から見ると、仮想インスタンスは引き続きアプリケーションサーバー、OSGiコンテナ、およびJVMを共有しますが、各インスタンスのデータはそれぞれ独自のスキーマに存在します。
テーブルカテゴリ
テーブルは2つのカテゴリーに分類されます。
-
パーティションテーブル には
companyId列が含まれており、物理的にはすべてのスキーマに存在します。 ほとんどのLiferay DXPテーブルはこのカテゴリに該当します。 -
コントロール テーブル は、デフォルトのスキーマから管理されます。 デフォルト以外のスキーマはビューを介してそれらを読み書きできますが、データは一箇所に保持されます。
制御テーブルはさらに2種類に分類されます。
-
純粋な制御テーブル は、デフォルトスキーマにのみ存在します。 リストには、
Company、VirtualHost、Release_、ServiceComponent、およびQUARTZ_テーブル (Liferay DXP のスケジュール済みジョブのストレージ) が含まれます。 他のスキーマは、更新可能なビューを介してこれらにアクセスします。 -
パーティション化された制御テーブル には
companyId列はありませんが、すべてのパーティションに存在します。 リストはClassName_、Counter、およびResourceActionです。 これらのテーブルのIDはパーティションごとに異なる場合があります。あるパーティションに追加されたクラス名は、他のパーティションにも独立して追加され、それぞれで異なる数値IDが割り当てられる可能性があります。
クォーツの職務行動
Liferay DXPは、スケジュールされたジョブを実行するためにQuartz(オープンソースのジョブスケジューラ)を使用します。 パーティショニングが有効になっている場合、Liferay DXP は永続化されたジョブ名とトリガー名に会社サフィックスを追加します: [ジョブ名]@[companyId]。 例えば、 @20001 で終わるジョブは、 companyId が 20001 である会社に属しています。 QUARTZ_ テーブルを検査したり、スケジューラのログをデバッグしたりする場合、サフィックスによってジョブがどのインスタンスから来たかがわかります。
アップグレードと動作確認
パーティショニングが有効になっている場合、Liferay DXP は、グローバルに一度実行するのではなく、企業ごとに一度ずつアップグレードプロセスと検証プロセス(アップグレード後に実行される組み込みのデータ整合性チェック)を実行します。 各スキーマは個別に新しいバージョンに移行されます。 仮想インスタンスの数が増えるにつれて、アップグレードにかかる時間も比例して長くなることが予想されます。
メッセージバスの動作
特定の companyId に紐付けられていないスケジュールされたジョブとメッセージバス (Liferay DXP の内部 pub/sub システム) リスナーは、デフォルトではアクティブな会社ごとに 1 回実行されます。 特定の宛先またはスケジューラ ジョブを除外するには、 コントロール パネル → 構成 → システム設定 → データベース パーティション構成 を介してエントリを構成します。
ヘッドレスAPIを使用した仮想インスタンスの管理
パーティショニングが有効になっている場合、 headless-portal-instances REST API を介して仮想インスタンスをプログラムでプロビジョニングおよび管理できます。 インスタンスを作成すると、そのスキーマが作成されます。インスタンスを削除すると、スキーマと会社レコードが同時に削除されます。
OpenAPI 仕様全体を参照し、リクエストを対話的に実行するには、API Explorer を http://[host]:[port]/o/api で開きます。
利用可能なポータルインスタンス操作は以下のとおりです。
| 操作 | 方法と経路 |
|---|---|
| 作成 | POST /o/headless-portal-instances/v1.0/portal-instances |
| リスト | GET /o/headless-portal-instances/v1.0/portal-instances |
| 既読 | GET /o/headless-portal-instances/v1.0/portal-instances/{portalInstanceId} |
| 更新 | PATCH /o/headless-portal-instances/v1.0/portal-instances/{portalInstanceId} |
| 有効にする | PUT /o/headless-portal-instances/v1.0/portal-instances/{portalInstanceId}/activate |
| 無効にする | PUT /o/headless-portal-instances/v1.0/portal-instances/{portalInstanceId}/deactivate |
| 削除 | DELETE /o/headless-portal-instances/v1.0/portal-instances/{portalInstanceId} |
例えば、この curl 呼び出しは、新しいインスタンスとその関連付けられたスキーマを作成します。 test@liferay.com:test を管理者の認証情報に置き換えてください。本番環境ではデフォルトの認証情報を使用しないでください。
curl -X POST 'http://localhost:8080/o/headless-portal-instances/v1.0/portal-instances' \
-H 'Content-Type: application/json' \
-u 'test@liferay.com:test' \
-d '{
"domain": "liferay.com",
"virtualHost": "localhost2",
"portalInstanceId": "pizzametro"
}'