我正在从API提供商处读取大量数据。获得响应后,我需要扫描并重新打包数据并放入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
task_url将导致以下内容:
logging.info('--------------------- Process File ---------------------')
user_key = ndb.Key(urlsafe=self.request.get('user_key'))
client_key = ndb.Key(urlsafe=self.request.get('client_key'))
cache_key = ndb.Key(urlsafe=self.request.get('cache_key'))
cache = cache_key.get()
data = json.loads(cache.data)
for property in data.values():
logging.info(property)
try:
key_name = '%s%s' % (property['key1'], property['key2'])
metadata = Metadata.get_or_insert(
key_name,
parent=user_key,
client_key=client_key,
# ... other info
)
metadata.put()
except StandardError, e:
logging.error(e.message)
所有任务都在后端运行。
有了这样的结构,它工作正常。好吧...大部分时间。 但有时我会收到此错误:
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.
似乎是过于频繁地写入数据存储区的问题?我想知道如何平衡节奏,让工人顺利进行...... 还有什么其他方法可以进一步提高性能吗?我的队列配置是这样的:
- name: worker0
rate: 120/s
bucket_size: 100
retry_parameters:
task_retry_limit: 3
答案 0 :(得分:2)
您一次只编写单个实体。
如何使用ndb.put_multi
修改代码以批量编写,这将减少每笔交易的往返时间。
为什么你使用get_or_insert,因为你每次都要覆盖记录。你不妨写一下。这两者都会减少很多工作量