SQLデータベースで自動インクリメントIDを簡単に作成できることはわかっていますが、Cassandraでそれを解決する良い方法はありますか? IDは、キーまたは列の名前用である必要があります。
数値のグローバルな連続したシーケンスを作成することは、分散システムでは実際には意味がありません。 ID を使用します。
(すべての参加者に同意し、単純な実装の下でシーケンスの進化を受け入れる必要があるため)
Cassandraの 軽量トランザクション を使用して、次のことはどうですか
CREATE TABLE ids (
id_name varchar,
next_id int,
PRIMARY KEY (id_name)
)
例えば:
INSERT INTO ids (id_name, next_id)
VALUES ('person_id', 1)
SELECT next_id FROM ids WHERE id_name = 'person_id'
結果がnext_id = 1だとしましょう
UPDATE ids SET next_id = 2 WHERE id_name = 'person_id' IF next_id = 1
結果は次のようになります。
[{[applied]: True}]
正常に更新された場合、または
[{[applied]: False, next_id: 2}]
他の誰かがすでに更新している場合。
したがって、Trueを取得した場合は、ID '1'を使用します-それはあなたのものです。それ以外の場合は、next_idをインクリメント(または、返されたnext_idを使用)して、プロセスを繰り返します。
良い解決策はありません。
または
少なくとも1つのインスタンスを超えると、IDの順序付けが複雑になります(少なくともスケーリングする場合)。これには、リレーショナルデータベースが含まれます。
使用できるカウンタデータ型があります。以下の例を考えてください。
CREATE KEYSPACE counterks WITH REPLICATION =
{ 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3 };
カウンター列のテーブルを作成します。
CREATE TABLE counterks.page_view_counts
(counter_value counter,
url_name varchar,
page_name varchar,
PRIMARY KEY (url_name, page_name)
);
カウンター列にデータをロードします。
UPDATE counterks.page_view_counts
SET counter_value = counter_value + 1
WHERE url_name='www.datastax.com' AND page_name='home';
カウンター値を見てください。
SELECT * FROM counterks.page_view_counts;
出力は次のとおりです。
url_name | page_name | counter_value
------------------+-----------+---------------
www.datastax.com | home | 1
カウンターの値を増やします。
UPDATE counterks.page_view_counts
SET counter_value = counter_value + 2
WHERE url_name='www.datastax.com' AND page_name='home';
カウンター値を見てください。
url_name | page_name | counter_value
------------------+-----------+---------------
www.datastax.com | home | 3
詳細については、こちらを参照してください: http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_counter_t.html
この質問はかなり古いですが、他の解決策で完成させたいと思います。
ノードの同期に依存するソリューションは不合理です。 IDの生成をブロックするか、重複したIDを作成することにより、確実にブレークします。
auto_increment_increment
およびauto_increment_offset
パラメーターを使用して、mysqlマスター/マスターレプリケーションで行われた方法を再現できます。
それを再現するには、ノードの数または予想されるノードの最大数を知る必要があり、各ノードで(非Cassandra)カウンター(例ごとにファイル)を作成する必要があります。
新しい数値を生成するたびに、現在の値を見つけ、増分を追加して保存します。まだ存在しない場合は、オフセットです。
したがって、10個のノードの場合、最初のノードの増分は10、オフセットは1、2番目のノードの場合は2などとなります。Node 1はID 1、11、21を作成します。Node 2はID 2、21、22を作成します。
IDを(おおよそ)ノード間で順序付けする場合は、共有カウンターを維持し、生成された各IDが共有カウンターよりも高いことを確認する必要があります。そうすれば、ノード/データセンターが長時間同期されない限り、大きな違いに気付かないはずです。
ID(受け入れ可能なソリューションである場合)の前にノード番号(または名前)を付けることで、基本的に同じことを行うことができます。また、ノードの数を知る必要はありません。 Node 1は1_1、1_2、1_3を作成します。Node 2は2_1、2_2、2_3を作成します。
私は、Cassandraが自動インクリメントフィールドを提供することを期待しているのは間違っていると思います
Cassandraはエレガントな分散型データベースであるため、自動インクリメントフィールドを提供することを期待しているため、この値は中央の場所で維持する必要があるため、元の目的に負担をかけ、無効にします。
したがって、DBが自動インクリメント数を取得するためのベースとなるソリューションを作成しないでください。
代わりに、アプリ内のコードまたはサービスでIDを生成します。これにより、ランダムな一意のIDを生成し続け、それを使用してデータモデルに適用できます。この方法では、Cassandra負けた
編集:この解決策は適切ではありません。最初のコメントを参照してください。
私の解決策:
1-IDテーブルを作成します。
CREATE TABLE ids (
id_name varchar,
next_id counter,
PRIMARY KEY (id_name)
)
2-自動増分キーを使用するテーブルに挿入する場合、次の手順を実行します。
2.1-最高の整合性レベルを使用して、増分カウンター(存在しない場合は作成されます)
UPDATE ids
SET next_id = next_id + 1
WHERE id_name = $AUTO_INCREMENTED_ID
USING CONSISTENCY ALL
2.2-新しいid値を取得します。
SELECT next_id
FROM ids
WHERE id_name = $AUTO_INCREMENTED_ID
2.3-自動インクリメントされたIDで値を挿入
INSERT INTO some_table ($AUTO_INCREMENTED_ID, ...)
VALUES ($RESULT_FROM_PREVIOUS_QUERY, ...)
私の答えで「$」で始まる言葉は、一目瞭然の(希望する)プレースホルダーです...
もちろん、これは推奨される方法ではありません。必要な場合にのみ使用してください。
それらは本当に連続している必要がありますか、それとも、人が簡単に入力できるUUIDよりもはるかに小さい数を数えるだけですか?
連番が本当に必要な場合は、次のいずれかを実行する必要があります。
cassandraのキー/ IDはジェネレーターのフィールドで、値は数値です...にテーブルがあります...カウントが正常に増加するまでループで条件付き更新を行います。考え)
次の番号を提供するジェネレーターサービスを用意してください。これは単一のシステムでのみ実行でき、単一障害点になる可能性がありますが、ニーズによってはこれが最適な場合があります。
あるいは...最初と同様ですが、一度に100個程度の数のバッチを取得し、それらをプロセス/スレッド内で処理します。これにより、競合が少なくなりますが、順序の保証はなく、一意性のみです。 。表示用に一意の短い数字のみが必要な場合は、これが最善の方法です。