1

我试图围绕争用以及它如何应用于应用程序引擎堆栈。

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

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)

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

我的问题是关于争用,我会受此影响吗?如果是,我该如何重组以防止它发生。

谢谢你。

4

4 回答 4

2

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

  1. 牺牲交易
  2. 批量写入 memcached
  3. 分片计数器
  4. 后台任务队列

https://developers.google.com/appengine/articles/sharding_counters

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

还有什么想法吗?我也想知道!

于 2012-05-27T17:20:41.500 回答
1

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

读取没有限制。

使用 memcache 缓存读取仍然是一个好主意,以降低成本并缩短响应时间。如果您使用 Python NDB,则默认启用缓存

解决方案:恕我直言,提高写入吞吐量和同时读取后端的好解决方案。它们(大部分)始终位于可用作共享内存的实例上。因此,您可以在并发读取的同时批量写入(并通过任务队列刷新)。

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

于 2012-05-27T19:58:46.880 回答
1

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

  1. Events实体不会像看起来那样支付任何争用税,从您的言辞和示例来看,只是任何实体组之外的根实体。
  2. 对单个实体的频繁更新可能会导致争用,但我几乎不怀疑所有者将每秒更新任何实体超过一次(1QPS 是您必须牢记的阈值,超过该阈值您就处于危险区域)。
  3. 数据存储读取操作不会导致争用问题。
于 2012-05-27T20:11:38.243 回答
1

在 App Engine 中,事件的每个实例都作为一个完整的对象进行读取/写入。您会担心每个 Event 实例的争用。如果您必须频繁更新 Event 的单个实例,那么您可能需要担心争用。如果您更新不同的实例,则无需担心。

我不确定您所说的争用究竟是什么意思。您可能指的是 a) 事务完整性或 b) 有限的写入性能。尽管您确实需要处理最终一致性问题,但您应该没有读取性能方面的问题。

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

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

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

通过这种方式,您可以分别编写每个有效负载,但成本会稍高一些,因为它们需要被索引,并且您需要按事件查询它们以获取它们。您可能希望将 Event 设置为祖先,以便您可以使用祖先查询进行一致的查询。

于 2012-05-27T22:33:46.607 回答