避免AppEngine中的争用

时间:2012-05-27 11:09:38

标签: google-app-engine contention

我试图围绕争用以及它如何应用于Application Engine堆栈。

我有一个像这样构建的模型

class Events(db.Model):
    #Owner Identification Number
    owner_id        = db.StringProperty(required=True)

    #Authentication Token
    auth_token      = db.StringProperty(required=True)

    #generic, b, c, d, ...
    driver          = db.StringProperty(required=True)

    #Start Time and Date
    tStart          = db.DateTimeProperty(auto_now=True)

    #Define whether the event is active or inactive
    active          = db.BooleanProperty(default=False)

    #Payload store, this will store each payload block sent or pulled
    payloads        = db.StringListProperty(indexed=False)

此模型包含多个事件,每个事件都有一个所有者和一个有效负载,事件的所有者将在其事件中写入有效负载,而许多其他事件将从事件中读取,这是一种转录堆栈。 / p>

我的问题是争论,我是否会受到影响,如果是这样的话,我该怎样才能进行重组以防止它发生。

谢谢。

4 个答案:

答案 0 :(得分:2)

我也是Google App Engine的新手。所以基本上避免争用实际上是在询问如何增加写入吞吐量。我能想到的解决方案是:

  1. 牺牲交易
  2. 批量写入memcached
  3. 碎片计数器
  4. 后台任务队列
  5. https://developers.google.com/appengine/articles/sharding_counters

    https://developers.google.com/appengine/articles/scaling/contention

    还有其他想法吗?我也想知道!

答案 1 :(得分:1)

在您的情况下,适用的限制是实体写入/更新限制,即每秒每个实体(或实体组)写入/更新1次。

读取没有限制。

使用memcache缓存读取仍然是个好主意,以降低成本并缩短响应时间。如果您使用Python NDB,那么caching is enabled by default

解决方案:恕我直言,提高写入吞吐量并同时进行读取的良好解决方案是backends。它们(大多数)总是在可以用作共享内存的实例上。因此,您可以在进行并发读取时批量写入(并通过任务队列刷新)。

注意:实例每天大约重启一次,因此您无法将它们视为可靠的存储 - 您可以将它们用作智能缓存,同时异步(通过后端线程或任务队列)事务更新实体数据存储。

答案 2 :(得分:1)

我认为您的模型没有任何问题:

  1. Events实体不会支付任何竞争税,因为从您的言论和示例来看,只是在任何实体组之外的根实体。
  2. 对单个实体的频繁更新可能会导致争用,但我几乎不怀疑所有者每秒会更新任何实体一次以上(1QPS是您必须记住的门槛,高于您处于危险区域的门槛)。
  3. 数据存储读取操作不会导致争用问题。

答案 3 :(得分:1)

在App Engine中,事件的每个实例都被读/写为整个对象。您会担心每个事件实例的争用。如果您必须经常更新单个事件实例,则可能需要担心争用。如果您更新不同的实例,则无需担心。

我不确定你的争论究竟是什么意思。您可能指的是a)事务完整性或b)有限的写性能。尽管你确实遇到了最终一致性问题,但你应该对阅读性能没有任何问题。

a)如果在更新Event实例后必须读取正确的数据,则需要按键使用数据存储区get()请求。 query()请求可能会返回旧数据。

b)如果您担心写入性能,则需要以某种方式将实体拆分为多个实体。您可能考虑为每个事件设置多个Payload实体,例如:

class Payload(db.Model):
    event = db.ReferenceProperty(Events)
    payload = db.StringProperty()

通过这种方式,您可以单独编写每个有效负载,但由于需要对其进行索引,因此需要稍微更加昂贵,因此需要按事件查询它们才能获取它们。您可能希望将Event设置为祖先,以便您可以使用祖先查询进行一致查询。