結果整合性のあるハイレプリケーションデータストアでAppEngineを使用しています。シャードカウンターも使用しています。
すべてのシャードを照会して合計すると、カウントが強く一貫していると想定できますか?つまり、以下のコードはシャードカウントの正確な合計を返しますか?
sum = 0
for counter in Counter.all():
sum += counter.count
結果整合性のあるハイレプリケーションデータストアでAppEngineを使用しています。シャードカウンターも使用しています。
すべてのシャードを照会して合計すると、カウントが強く一貫していると想定できますか?つまり、以下のコードはシャードカウントの正確な合計を返しますか?
sum = 0
for counter in Counter.all():
sum += counter.count
いいえ。キーでフェッチする場合でも、強一貫性のあるカウントに依存することはできません(ただし、そうでない場合よりも最新になります)。バッチ取得操作はトランザクションではないため、シャードのフェッチ中にシャードの1つが更新される可能性があります。
ただし、ここで強い一貫性を求めることは、意味がありません。まず、App Engineのような分散システムでは、同時性は最良の場合にはファジーコンセプトです。同期には調整が必要であり、ボトルネックが発生します。第2に、カウンター値のトランザクション合計を取得できたとしても、カウンターを読み取った直後にカウンターを更新できるため、取得した瞬間に古くなってしまいます。
強一貫性のあるシャードカウンターを作成する場合は、クエリではなくキーを使用する必要があります。
#for getting
total = 0
shard_keys = []
for i in range(20): #20 shards
key_name = shard + str(i)
shard_keys.append(db.Key.from_path('Counter', key_name))
counters = db.get(shard_keys)
for counter in counters:
if counter:
total += counter.count
#for incrementing a shard
import random
key_name = 'shard' + str(int(random.random()*20)) #choose a random shard
counter = Counter.get_by_key_name(key_name) #try to retrieve from datastore
if not counter:
counter = Counter(key_name=key_name) #shard doesn't exist, create one
counter.count += 1
db.put(counter)
一貫性を確保するために、トランザクション内でインクリメントを実行します。
シャーディングされたカウンターが現在の状態を合計する確率を上げることはできますが、(私が知っている限りでは)その確率を100%にすることはできません。
クエリは最終的にHRDで整合性があるため、クエリを介して取得したエンティティが更新されているかどうかを確認することはできません。クエリが更新されているエンティティプロパティに依存している場合、クエリはエンティティを見つけられない可能性があります。