ユユユユユ

webエンジニアです

書き込みコンフリクトを制御する

 複数リーダーレプリケーションは書き込みコンフリクトの発生を防ぐことができない。またその解消を非同期的に実施する必要がある。「同期的にコンフリクトを検出したい」というのは本質的に単一リーダーがトランザクションで実現すべきことがらであるから、前提として成立しない。コンフリクトが発生することをできるだけ避けるように設定することが可能であっても、可能性をゼロにすることは複数リーダーの性質上不可能である。

 複数の書き込み結果が存在してしまうとき、何らかのアルゴリズムによって、それらを最終的な値に解決しなければならない。具体的にはこんなやり方がありうる。

  • 書き込みログにユニークな値を付与し、より大きい値を持つ書き込みを優先する
  • レプリカごとにユニークな値を付与し、より大きい値を持つレプリカを優先する
  • コンフリクトした値を連結( concatenate )してしまう
  • コンフリクトそのものをデータ構造として保存し、後続の読み込み時にユーザー自身に修正させる

 例えば CouchDB はコンフリクト状態を一時的に保存し、読み込みリクエストに対して複数のレコードを返すような実装になっている。コンフリクトの解消はアプリケーション開発者に委ねられており、任意のアルゴリズムで最終的な値を自動的に決定することもできるし、コンフリクトをそのまま表示し、エンドユーザーに修正をせまることもできる。

 コンフリクトの解消は得てしてエラーを招きいれやすい。 Amazon のショッピングカートのバグは有名な事例である。カートへの書き込みでコンフリクトが生じた場合は、商品の追加を商品の削除に優先するというロジックにバグが存在し、「カートから商品を削除してもいつのまにか商品が復活する」という奇妙な動作を発生させていたのである1。自動的かつ穏当なやり方でコンフリクトを解消するための方法論はいまだ研究の途上にある。技術として発展途上であるから、一般のデータベース製品においてもほとんど対応されていないというのが正直なところである。