GAE/P: 为计数器使用延迟任务和交易
GAE/P: Using deferred tasks and transactions for a counter
我的应用程序中有一个计数器,我希望 99% 的时间在用事务更新计数器时不会出现争用问题。
为了在繁忙时处理 1% 的时间,我正在考虑通过使用延迟任务中的事务来更新计数器,如下所示:
def update_counter(my_key):
deferred.defer(update_counter_transaction)
@ndb.transactional
def update_counter_transaction(my_key):
x = my_key.get()
x.n += 1
x.put()
偶尔出现争用导致交易失败的情况,会重试任务。
我熟悉分片计数器,但这似乎更容易,也适合我的情况。
我是否缺少任何可能导致此解决方案无法正常工作的内容?
自动任务重试可能存在问题,至少理论上可能会因而不是预期计数器增量的事务冲突而发生。如果这种不希望的重试成功地重新执行了计数器增量代码,则计数器值可能会被丢弃(将高于预期值)。 可能或可能不会适合您的应用,具体取决于计数器的用途。
这是一个不希望的延迟任务调用示例:
这个问题的答案似乎与关于常规任务队列的注释一致 documentation (I saw no such note in the deferred task queues article,但我在脑海中将其标记为可能):
Note that task names do not provide an absolute guarantee of once-only
semantics. In extremely rare cases, multiple calls to create a task of
the same name may succeed, but in this event, only one of the tasks
would be executed. It's also possible in exceptional cases for a task
to run more than once.
从这个角度来看,可能实际上让计数器与其他相关 logical/transactional 操作(如果有的话)一起递增比将其隔离更好任务队列上的单独事务。
我的应用程序中有一个计数器,我希望 99% 的时间在用事务更新计数器时不会出现争用问题。
为了在繁忙时处理 1% 的时间,我正在考虑通过使用延迟任务中的事务来更新计数器,如下所示:
def update_counter(my_key):
deferred.defer(update_counter_transaction)
@ndb.transactional
def update_counter_transaction(my_key):
x = my_key.get()
x.n += 1
x.put()
偶尔出现争用导致交易失败的情况,会重试任务。
我熟悉分片计数器,但这似乎更容易,也适合我的情况。
我是否缺少任何可能导致此解决方案无法正常工作的内容?
自动任务重试可能存在问题,至少理论上可能会因而不是预期计数器增量的事务冲突而发生。如果这种不希望的重试成功地重新执行了计数器增量代码,则计数器值可能会被丢弃(将高于预期值)。 可能或可能不会适合您的应用,具体取决于计数器的用途。
这是一个不希望的延迟任务调用示例:
这个问题的答案似乎与关于常规任务队列的注释一致 documentation (I saw no such note in the deferred task queues article,但我在脑海中将其标记为可能):
Note that task names do not provide an absolute guarantee of once-only semantics. In extremely rare cases, multiple calls to create a task of the same name may succeed, but in this event, only one of the tasks would be executed. It's also possible in exceptional cases for a task to run more than once.
从这个角度来看,可能实际上让计数器与其他相关 logical/transactional 操作(如果有的话)一起递增比将其隔离更好任务队列上的单独事务。