MR_COUNTERデータ型の使用
複数リージョン表でのCRDTデータ型の使用
MR_COUNTERデータ型の概要
MR_Counterデータ型はカウンタCRDTです。CRDTは、競合のないレプリケートされるデータ型を表します。Oracle NoSQL Databaseの複数リージョン設定においては、CRDTとは、リージョンを個別に更新でき正しい共通状態で収束できるサーバー間でレプリケート可能なデータ型です。リージョン内の変更は同時実行され、相互に同期されません。つまり、CRDTを使用すると、ユーザーの介入なしにリージョン間で同時変更をマージできます。Oracle NoSQL Databaseでは、現在、MR_CounterというカウンタCRDTがサポートされています。MR_COUNTERデータ型はINTEGER、LONGまたはNUMBERデータ型のサブタイプです。スキーマレスJSONフィールドでMR_COUNTERデータ型を使用することもできます。つまり、JSONドキュメント内の1つ以上のフィールドをMR_COUNTERデータ型にできます。
複数リージョン表でMR_Counterが必要なのはなぜですか。
複数リージョンのデータベース構成では、同じデータのコピーを複数のリージョンに格納する必要があります。この構成では、異なるリージョンでデータが同時に変更される可能性があるという事実に対処する必要があります。
3つの異なるリージョン(データが3つの異なるOracle NoSQL Databaseストアに格納されているリージョン)にある複数リージョン表の例を考えてみます。リージョンをホストしているマシン間で調整を行わずに複数のリージョンの同じデータを同時に更新すると、リージョン間で不整合が発生する可能性があり、一般的な場合は解決できないことがあります。更新間で競合が発生した場合、リストアの一貫性とデータ整合性のために、更新の一部またはすべてを完全または部分的に削除する必要がある場合があります。たとえば、Oracle NoSQL Database内の複数リージョン表の現在の構成では、複数リージョン表の同じ列(カウンタ)が異なる値で同時に2つのリージョンにわたって更新されると、競合が発生します。
現在、競合解消方法では、最新の書込みによって複数のリージョンにわたる値が上書きされます。たとえば、リージョン1は値R1でcolumn1を更新し、region2は値R2でcolumn1を更新します。region1の後にregion2の更新が発生すると、両方のリージョンの列(カウンタ)の値はR2になります。これは実際には望ましくありません。かわりに、各リージョンの最後に列(カウンタ)を更新する必要があります。また、システム内部でリージョン間の列の合計を決定する必要もあります。
この競合を処理する1つの方法は、シリアライズ可能/線形化可能なトランザクションを作成することです(1つのトランザクションが完了し、すべてのリージョンで変更が同期されてから、次のトランザクションが発生します)。シリアライズ可能トランザクションがあると、パフォーマンスに大きな問題が発生します。ここでは、MR_COUNTERデータ型が便利です。MR_COUNTERデータ型では、シリアライズ可能なトランザクションは必要なく、競合解消が行われます。つまり、MR_COUNTERデータ型を使用すると、異なるリージョンでデータ変更を同時に実行できますが、データは常に一貫性のある状態にマージできます。このマージは、特別な競合解消コードやユーザーの介入なしに、MR_COUNTERデータ型によって自動的に実行されます。
MR_COUNTERデータ型のユースケース
顧客に異なるサービスとパッケージを提供する電気通信プロバイダを考えてみます。このようなサービスには、顧客とその家族がデータ使用プランを共有する「ファミリ・プラン」オプションがあります。顧客には、顧客の家族全員が集合的に使用する月の無料データ使用量制限が割り当てられます。顧客の家族の合計使用量がデータ制限の90%に達すると、電気通信プロバイダは顧客にアラートを送信します。顧客のファミリ・プランに、異なる物理的な地域に分散している4つのメンバーがいるとします。家族の合計消費量が無料使用量の90%に達すると、顧客は電気通信プロバイダからアラートを受け取る必要があります。レイテンシ、スループットおよびパフォーマンスの向上のために、データは異なるリージョンにレプリケートされます。つまり、4つのリージョンがあり、それぞれに顧客のデータ使用量の詳細を含むkvstoreがあるということです。ファミリ・メンバーの使用量は様々なリージョンで更新する必要があり、任意の時点の合計使用量を監視し、データ使用量が制限に達した場合はアラートを送信する必要があります。
MR_COUNTERデータ型は、異なるリージョン間でデータの使用量を競合のない方法で追跡する場合に理想的です。前述の例では、すべてのデータ・リージョンのデータ・ストアの増分カウンタによって、そのリージョンのデータ使用量が追跡されます。すべてのリージョンの統合されたデータの使用量は、ユーザーの介入なしに任意の時点で決定できます。つまり、任意の時点での合計データ使用量は、MR_COUNTERデータ型を使用して簡単に決定できます。
MR_COUNTERデータ型のタイプ
現在、Oracle NoSQL DatabaseでサポートされているMR_COUNTERデータ型は、Positive-Negative (PN)カウンタのみです。
Positive-Negative (PN)カウンタ
PNカウンタは増分または減分できます。したがって、これらは汎用カウンタとして機能します。たとえば、これらのカウンタを使用して、ソーシャル・メディアWebサイトでアクティブなユーザーの数をいつでもカウントできます。ユーザーがオフラインになったら、カウンタを減分する必要があります。
MR_COUNTER列を含む複数リージョン表を作成するには、管理者ガイドのMR_COUNTER列を含む複数リージョン表の作成に関する項を参照してください。
- 表作成でのスキーマ定義時。
- スキーマにフィールドを追加する際のスキーマ定義時。
MR_COUNTERデータ型を使用した表の作成
CREATE TABLE文で表内のMR_Counterデータ型の列を宣言できます。これは、複数リージョン表でのみ実行できます。
MR_COUNTERデータ型で列を宣言します。MR_COUNTERはINTEGER、LONGまたはNUMBERデータ型のサブタイプです。JSON列内のフィールドをMR_COUNTERデータ型として宣言することもできます。
mr_counter_defintion := AS MR_COUNTER
セマンティクス:
列の型をMR_COUNTER型として宣言します。
MR_COUNTER列の特性:
- MR_COUNTERデータ型は、複数リージョン表にのみ使用できます。通常の表では使用できません。
- 1つの表には、MR_COUNTERとして定義された複数の列を含めることができます。
- MR_COUNTER列をCREATE TABLE DDL文の一部として作成するか、ALTER TABLE DDL文を使用して既存の表にMR_COUNTER列を追加します。
- JSON列内のどのフィールドも、MR_COUNTERとして定義できます。
- MR_COUNTERデータ型のデフォルト値は必ず0になります。
- MR_COUNTERをARRAYの要素にはできません。
ノート:
MR_COUNTERは、主キーにすることも、2次索引の一部にすることもできません。MR_COUNTERデータ型の使用例 - 複数リージョン表でのPNカウンタ・データ型の作成
CREATE Table myTable( name STRING,
count INTEGER AS MR_COUNTER,
PRIMARY KEY(name)) IN REGIONS DEN,LON;
前述の例では、2つのリージョンDENおよびLONにPNカウンタ・データ型を作成します。
- INSERT句でDEFAULTキーワードを指定した場合、次のようになります。
INSERT INTO myTable VALUES ("Bob", DEFAULT);
- INSERT句の列をスキップすると、次のようになります。
INSERT INTO myTable(name) VALUES ("Bob");
ノート:
MR_COUNTER
の場合、単一リージョンによって発生した件数がオーバーフローする可能性はありませんが、MR_COUNTER
値(すべてのリージョンについての件数の合計)はオーバーフローする可能性があります。
たとえば、前述の表myTable
には、INTEGERのMR_COUNTER
があり、DENとLONという2つのリージョンがあります。リージョンDENでは、count
をINTEGER.MAX
より大きい合計値では増分できません。これは、リージョンLONにも当てはまります。
ただし、リージョンDENでcount
がINTEGER.MAX
ずつ増分され、リージョンLONでそれが2ずつ増分された場合、count
の値は(INTEGER.MAX
.+2)になりオーバーフローしていますが、これは許容されます。
CREATE TABLE demoJSONMR(name STRING,
jsonWithCounter JSON(counter as INTEGER MR_COUNTER,
person.count as LONG MR_COUNTER),
PRIMARY KEY(name)) IN REGIONS FRA,LON;
counter
であり、これはINTEGER MR_COUNTERデータ型です。2番目のフィールドは、埋込みJSONドキュメント(person
)内のcount
です。このcount
フィールドはLONG MR_COUNTERデータ型です。
ノート:
JSONドキュメント内で作成するMR_COUNTERデータ型の数に制限はありません。例: JSON MR_COUNTERを使用した複数リージョン表へのデータの挿入
ノート:
- ゼロ以外の値を明示的に指定した場合でも、すべてのMR_COUNTERデータ型に最初に値0が割り当てられます。これは、INTEGER、LONGまたはNUMBER以外の値を指定しようとした場合も有効です。
- JSON MR_COUNTERの挿入時にキーワードDEFAULTを指定することはできません。
- 宣言されたJSON MR_COUNTERフィールドに値を指定せずに、またはキーワードDEFAULTを使用せずに、MR表にデータを挿入しようとすると、エラーが返されます。
INSERT INTO demoJSONMR VALUES ("Anna",
{
"id" : 1,
"counter" : 0,
"person" : {
"age" : 10,
"count" : 0,
"number" : 100
}
}
);
SELECT * FROM demoJSONMR;
{"name":"Anna",
"jsonWithCounter":{"id" : 1,"counter":0,
"person":{"age":10,"count":0,"number":100}
}
}