18

用語の間違いはご容赦ください。特に、リレーショナルデータベースの用語を使用しています。

CouchDBCassandraなど、他の多くのプロジェクトとともに、多数の永続的なKey-Valueストアがあります。

それらに対する典型的な議論は、それらが複数の行またはテーブルにわたるアトミックトランザクションを一般的に許可しないということです。一般的なアプローチでこの問題を解決できるのではないかと思います。

たとえば、一連の銀行口座の状況を考えてみましょう。ある銀行口座から別の銀行口座にお金を移動するにはどうすればよいですか?各銀行口座が行である場合、同じトランザクションの一部として2つの行を更新し、一方の値を減らし、もう一方の値を増やします。

明らかなアプローチの1つは、トランザクションを説明する別のテーブルを用意することです。次に、ある銀行口座から別の銀行口座にお金を移動するには、このテーブルに新しい行を挿入するだけです。2つの銀行口座のいずれの現在の残高も保存せず、代わりにトランザクションテーブルの適切な行をすべて合計することに依存します。ただし、これは非常に手間がかかることは容易に想像できます。銀行には1日に数百万のトランザクションがあり、個々の銀行口座には数千の「トランザクション」が関連付けられている場合があります。

基になるデータが最後に取得してから変更された場合、多数の(すべて?)Key-Valueストアがアクションを「ロールバック」します。おそらく、これを使用してアトミックトランザクションをシミュレートし、特定のフィールドがロックされていることを示すことができます。このアプローチには明らかな問題がいくつかあります。

他のアイデアはありますか?私のアプローチが単に間違っていて、新しい考え方に頭を悩ませていない可能性は十分にあります。

4

5 に答える 5

13

たとえば、単一のドキュメント (リレーショナル用語では行) の値をアトミックに更新したい場合は、CouchDB で行うことができます。他の競合するクライアントが同じドキュメントを読んだ後に更新した場合、変更をコミットしようとすると競合エラーが発生します。次に、新しい値を読み取り、更新してコミットを再試行する必要があります。このプロセスを繰り返さなければならない回数は不確定です (多くの競合がある場合は無限になる可能性があります) が、コミットが成功した場合は、原子的に更新されたバランスでデータベースにドキュメントがあることが保証されます。

2 つの残高を更新する必要がある場合 (つまり、1 つの口座から別の口座への送金)、金額と 2 つの口座 (入出金) を格納する別の取引ドキュメント (事実上、行が取引である別のテーブル) を使用する必要があります。 . ちなみに、これは簿記の一般的な方法です。CouchDB は必要な場合にのみビューを計算するため、実際には、そのアカウントをリストするトランザクションからアカウントの現在の金額を計算することは非常に効率的です。CouchDB では、口座番号をキーとして発行し、トランザクションの金額 (受信の場合は正、送信の場合は負) を出力する map 関数を使用します。reduce 関数は、各キーの値を単純に合計し、同じキーと合計を発行します。次に、 group=True を指定したビューを使用して、口座番号をキーとした口座残高を取得できます。

于 2009-07-07T20:56:26.677 に答える
5

CouchDB は、ロックとアトミック操作をサポートしていないため、トランザクション システムには適していません。

銀行振込を完了するには、いくつかのことを行う必要があります。

  1. トランザクションを検証し、ソース アカウントに十分な資金があること、両方のアカウントが開いていること、ロックされていないこと、良好な状態にあることなどを確認します。
  2. 元の口座の残高を減らす
  3. 送金先口座の残高を増やす

これらのステップのいずれかの間に変更が加えられた場合、アカウントの残高またはステータスは、送信後にトランザクションが無効になる可能性があり、この種のシステムでは大きな問題です。

「送金」レコードを挿入し、map/reduce ビューを使用して最終口座残高を計算する上記のアプローチを使用したとしても、ソース口座をオーバードローしないことを保証する方法はありません。ソース口座の残高の確認と、残高の確認後に 2 つのトランザクションを同時に追加できるトランザクションの挿入との間の競合状態。

だから...それは仕事には間違ったツールです. CouchDB はおそらく多くのことを得意としていますが、これは実際にはできないことです。

編集: 現実世界の実際の銀行が結果整合性を使用していることは、おそらく注目に値します。銀行口座を十分に長く借りると、当座貸越手数料が発生します。あなたが非常に上手であれば、残高を確認し、お金を発行し、取引を記録する競合状態があるため、ほぼ同時に2つの異なるATMからお金を引き出して、アカウントをオーバードローすることさえできるかもしれません. 小切手をアカウントに入金すると、残高が増えますが、実際には、元のアカウントに実際に十分なお金がない場合に備えて、一定期間それらの資金を保持します。

于 2011-10-25T03:38:47.117 に答える
1

それらに対する典型的な議論は、複数の行またはテーブルにまたがるアトミック トランザクションを一般に許可しないというものです。この問題を解決する一般的なアプローチがあるのだろうか。

最新のデータ ストアの多くは、そのままではアトミック マルチキー更新 (トランザクション) をサポートしていませんが、それらのほとんどは、ACID クライアント側トランザクションを構築できるプリミティブを提供しています。

データ ストアがキーごとの線形化可能性と、比較と交換またはテストと設定の操作をサポートしている場合は、シリアル化可能なトランザクションを実装するだけで十分です。たとえば、このアプローチはGoogle の PercolatorCockroachDBデータベースで使用されています。

私のブログでは、シリアライズ可能なクロス シャード クライアント側トランザクションの段階的な視覚化を作成し、主要なユース ケースを説明し、アルゴリズムのバリアントへのリンクを提供しました。データストアにそれらを実装する方法を理解するのに役立つことを願っています.

キーごとの線形化可能性と CAS をサポートするデータ ストアには、次のものがあります。

  • 軽量トランザクションの Cassandra
  • 一貫したバケットを持つRiak
  • RethinkDB
  • 飼育係
  • その他
  • HBase
  • DynamoDB
  • モンゴDB

ところで、Read Committed 分離レベルに問題がない場合は、Peter BailisによるRAMP トランザクションを調べるのが理にかなっています。これらは、同じデータ ストアのセットに対して実装することもできます。

于 2016-03-04T06:46:24.913 に答える
1

BerkeleyDB と LMDB はどちらも、ACID トランザクションをサポートするキー値ストアです。BDB では txns はオプションですが、LMDB はトランザクションでしか動作しません。

于 2014-08-05T00:51:05.170 に答える