Resetting CRDT values#
CRDT値のリセットは可能ですが、特別な処理が必要です。クラスターの非同期の性質は、実装方法に関係なく、さまざまなノードが変更ストリームのさまざまな場所でリセット操作を認識する可能性があることを意味します。別のノードが同時にリセットを開始する場合があります。つまり、他のノードからリセットを観察する前に。
言い換えれば、リセット操作を正しく動作させるには、通常の操作に対して可換である必要があります。単一ノードでうまく機能する可能性のある値をリセットする多くの単純な方法は、この理由で失敗します。
CRDT値をリセットする際の課題#
たとえば、値をリセットする最も簡単なアプローチは次のとおりです。
UPDATE crdt_table SET cnt = 0 WHERE id = 1;
状態ベースのCRDTでは、これは機能しません。他のノードの状態を破棄しますが、ローカルでのみです。リモートノードのマージファンクションによって追加され、値の発散を引き起こし、最終的に他のノードでの変更によりそれを受信します。
オペレーションベースのCRDTでは、更新が-cnt
の減算として解釈されるため、これは機能するように見える場合があります。ただし、それは同時リセットがない場合にのみ機能します。
2つのノードが同時にリセットを実行しようとすると、デルタが2回適用され、負の値を取得しますリセットからは予想されません。
DELETE + INSERT
をリセットとして使用できるように見えるかもしれませんが、このアプローチにはいくつかの弱点もあります。行が同じキーで再挿入された場合、他のノードからの変更に関して操作ストリームの同じ位置ですべてのノードがそれを見るという保証はありません。
PGDは、コンカレントケースでデータ異常を引き起こす可能性があるため、同じ主キー値の再利用を特にお勧めしません。
CRDT値のリセットを確実に処理する方法#
状態ベースのCRDTタイプは、次のような特別な!
演算子を使用してリセットを確実に処理できます。
UPDATE tab SET counter = !counter WHERE ...;
「確実に」とは、値にマルチプルの同時リセットと発散という2つの問題がないことを意味します。
オペレーションベースのCRDTタイプは、複数の同時リセットが回避されるため、 How Quorum Commit works などのEager Replicationを実行するコミットスコープを使用してのみ確実にリセットできます。クォーラムコミットスコープを使用して、いずれかの種類のCRDTを特定の値に設定することもできます。