【问题标题】:Using Google App Engine transaction使用 Google App Engine 交易
【发布时间】:2016-02-04 13:16:31
【问题描述】:

我有两个任务(ab)应该在事务中执行以避免不一致。我可能需要执行其中一项任务或同时执行两项任务。

在下面的代码中function_a 执行task afunction_b 执行task b

@ndb.transactional
def function_a():
    # basic validations
    # read entity of type A
    # make changes to entity
    # write entity
    return

@ndb.transactional
def function_b():
    # basic validations
    # read entity of type B
    # make changes to entity
    # write entity
    return

所以如果我需要一起执行任务 a 和 b。我可以执行如下操作:-

def function_ab():
    function_a()
    function_b()
    return

但是这个实现不会同时保持AB 的一致性,所以我也需要让它成为事务性的。

@ndb.transactional
def function_ab():
    function_a()
    function_b()
    return

因此,在这样的实现中,为了代码的可重用性,多次使用事务(一次在function_ab 上一次,一次用于个人funcion_afunction_b)。如果我不追求代码可重用性,我可以执行以下操作:-

@ndb.transactional
def function_ab():
    # basic validations
    # read entity of type A
    # make changes to entity
    # write entity

    # basic validations
    # read entity of type B
    # make changes to entity
    # write entity    
    return

我不太了解事务在应用程序引擎中的工作方式,所以我的问题是,使用具有代码可重用性的事务是否有任何缺点(性能等),而不是我不追求代码可重用性并且采用代码可重用性方法真的有用吗?

【问题讨论】:

    标签: google-app-engine transactions google-cloud-datastore app-engine-ndb


    【解决方案1】:

    你不能嵌套事务,你的事务function_ab() 会报错。

    但是您仍然可以通过确保只有顶层函数是事务性的,而内部函数只是检查它们是否确实在事务中,来安排代码以供重用。也许是这样的:

    def function_a():
        assert ndb.in_transaction()
        return
    
    def function_b():
        assert ndb.in_transaction()
        return
    
    @ndb.transactional
    def function_ab(do_a, do_b):
        if do_a:
            function_a()
        if do_b:
            function_b()
    

    您的使用模式实际上是教科书式的,适合使用 ndb async tasklet,效率更高。在Tasklets, Parallel Queries, Parallel Yield 中查找get_cart_plus_offers() 示例。

    【讨论】:

    • 应用引擎中的嵌套事务工作正常,因为我通过编写一些代码进行了测试,get_cart_plus_offers() 用于从数据库读取数据,而不是用于将数据写入数据库。 gist.github.com/kumar003vinod/603f883f388413fa626e
    • 嵌套事务可能(我不确定)在您的情况下有效,因为这两个函数不会导致冲突,因为它们在不同的实体上运行,不确定。但那不是我的情况。
    • 只需将 get_async() 替换为 assignments 加上 put_async(),您就可以对 db tasklet 进行类似的写入(该文章中有更多示例)。小任务是读还是写并不重要,关键是并行执行它们(这是可能的,因为它们在不同的实体上操作)。否则它们将被序列化。大量操作可能会对性能产生巨大影响。
    • 因此,如果我们对不同的实体使用嵌套事务并且没有得到任何错误,而答案中建议的方式(我们只使用一个事务)会不会对性能产生影响?
    • 我所指的性能影响与嵌套事务无关(它甚至发生在同一个事务中) - 它来自使用序列化的同步数据库访问与异步任务可以并行发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    相关资源
    最近更新 更多