Google App Engine (Python) 处理大量写任务

在使用 Google App Engine (Python) 读取大量数据时,我们需要将数据重新打包并存储到 App Engine 数据存储中。对于一个大型帐户,可能会包含大约 50,000 个条目。每次从 API 获取一些条目时,我们都会将 500 个条目作为一批存储在临时表中,然后将处理任务发送到队列。为了防止在一个队列中塞入太多任务,我们总共使用了 6 个队列:
在这里插入图片描述

count = 0 
worker_number = 6
for folder, property in entries:
                    data[count] = {
                        # repackaging data here
                    }

                    count = (count + 1) % 500

                    if count == 0:
                        cache = ClientCache(parent=user_key, data=json.dumps(data))
                        cache.put()
                        params = {
                            'access_token': access_token,
                            'client_key': client.key.urlsafe(),
                            'user_key': user_key.urlsafe(),
                            'cache_key': cache.key.urlsafe(),
                        }
                        taskqueue.add(
                            url=task_url,
                            params=params,
                            target='dbworker',
                            queue_name='worker%d' % worker_number)
                        worker_number = (worker_number + 1) % 6

所有的任务都在后端运行。这样的结构在大多数情况下都可以正常工作。但是,有时我们会遇到以下错误:

2013-09-19 15:10:07.788
suspended generator transaction(context.py:938) raised TransactionFailedError(The transaction could not be committed. Please try again.)
W 2013-09-19 15:10:07.788
suspended generator internal_tasklet(model.py:3321) raised TransactionFailedError(The transaction could not be committed. Please try again.)
E 2013-09-19 15:10:07.789
The transaction could not be committed. Please try again.

似乎是向数据存储中写入数据过于频繁导致的问题。我们希望找到一种方法来平衡写入数据的速度,让工作者可以顺利运行。

解决方案

1. 使用 ndb.put_multi 批量写入数据

def write_in_batches(data):
  """Write data to the datastore in batches."""

  batch_size = 500
  for i in range(0, len(data), batch_size):
    batch = data[i:i+batch_size]
    ndb.put_multi(batch)

2. 使用 ndb.Key.put() 直接写入数据,而不是使用 get_or_insert()

def write_directly(data):
  """Write data to the datastore directly."""

  for property in data.values():
    key_name = '%s%s' % (property['key1'], property['key2'])
    metadata = Metadata(
        id=key_name,
        parent=user_key,
        client_key=client_key,
        # ... other info
    )
    metadata.put()

3. 调整队列配置

- name: worker0
  rate: 500/s
  bucket_size: 1000
  retry_parameters:
    task_retry_limit: 3

4. 其他建议

  • 考虑使用 memcache 或 Redis 等缓存系统来减少对数据存储的访问。
  • 使用异步任务来处理数据,这可以提高应用程序的整体性能。
  • 使用 Cloud Datastore 索引来提高查询性能。
  • 使用 Cloud Datastore 强一致性来确保数据的一致性。
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值