我将 App Engine 与最终一致的高复制数据存储一起使用。我也在使用分片计数器。
当我查询所有分片并将它们相加时,我可以假设计数是强一致的吗?也就是说,下面的代码会返回我的分片计数的准确总和吗?
sum = 0
for counter in Counter.all():
sum += counter.count
我将 App Engine 与最终一致的高复制数据存储一起使用。我也在使用分片计数器。
当我查询所有分片并将它们相加时,我可以假设计数是强一致的吗?也就是说,下面的代码会返回我的分片计数的准确总和吗?
sum = 0
for counter in Counter.all():
sum += counter.count
不。即使按键获取,您也不能依赖高度一致的计数(尽管它会比其他方式更新)。批量获取操作不是事务性的,因此可以在您获取它们时更新其中一个分片。
然而,在这里要求强一致性是没有意义的。首先,在像 App Engine 这样的分布式系统中,同时性在最好的时候是一个模糊的概念——同步需要协调,这会产生瓶颈。其次,即使您可以获得计数器值的交易总和,但在您获取它的那一刻它已经过时了,因为无论如何在您阅读它们之后计数器可以立即更新。
如果你想创建强一致的分片计数器,你应该使用键,而不是查询。
#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 中的查询最终是一致的,因此您无法确定通过查询获得的实体是否已更新。如果查询依赖于正在更新的实体属性,则查询甚至可能找不到实体。