推荐的用于备份appengine数据存储的策略

现在我使用remote_api和appcfg.py download_data来每天晚上拍摄我的数据库的快照。 这需要很长时间(6小时),而且很贵。 如果没有滚动我自己的基于变更的备份(我会太害怕做这样的事情),确保我的数据从失败中安全的最佳选择是什么?

PS:我承认Google的数据可能比我的更安全。 但是如果有一天我不小心编写了一个删除它的程序呢?


我认为你几乎确定了你所有的选择。

  • 请相信Google不要丢失您的数据,并希望您不会意外指示他们销毁数据。
  • 使用download_data执行完整备份,如果费用过高,则可能不如每晚一次。
  • 推出自己的增量备份解决方案。
  • 选项3实际上是一个有趣的想法。 您需要在所有实体上修改时间戳,并且不会捕获已删除的实体,但除此之外,它对于remote_api和游标非常有用。

    编辑

    这是一个简单的增量下载器,用于remote_api。 此外,注意事项是它不会注意到已删除的实体,并且假定所有实体都将最后一次修改时间存储在名为updated_at的属性中。 在你自己的危险中使用它。

    import os
    import hashlib
    import gzip
    from google.appengine.api import app_identity
    from google.appengine.ext.db.metadata import Kind
    from google.appengine.api.datastore import Query
    from google.appengine.datastore.datastore_query import Cursor
    
    INDEX = 'updated_at'
    BATCH = 50
    DEPTH = 3
    
    path = ['backups', app_identity.get_application_id()]
    for kind in Kind.all():
      kind = kind.kind_name
      if kind.startswith('__'):
        continue
      while True:
        print 'Fetching %d %s entities' % (BATCH, kind)
        path.extend([kind, 'cursor.txt'])
        try:
          cursor = open(os.path.join(*path)).read()
          cursor = Cursor.from_websafe_string(cursor)
        except IOError:
          cursor = None
        path.pop()
        query = Query(kind, cursor=cursor)
        query.Order(INDEX)
        entities = query.Get(BATCH)
        for entity in entities:
          hash = hashlib.sha1(str(entity.key())).hexdigest()
          for i in range(DEPTH):
            path.append(hash[i])
          try:
            os.makedirs(os.path.join(*path))
          except OSError:
            pass
          path.append('%s.xml.gz' % entity.key())
          print 'Writing', os.path.join(*path)
          file = gzip.open(os.path.join(*path), 'wb')
          file.write(entity.ToXml())
          file.close()
          path = path[:-1-DEPTH]
        if entities:
          path.append('cursor.txt')
          file = open(os.path.join(*path), 'w')
          file.write(query.GetCursor().to_websafe_string())
          file.close()
          path.pop()
        path.pop()
        if len(entities) < BATCH:
          break
    
    链接地址: http://www.djcxy.com/p/9915.html

    上一篇: Recommended strategies for backing up appengine datastore

    下一篇: Problems reading cookies in Sharepoint with anonymous access