7

지금 당장 remote_api와 appcfg.py download_data을 사용하여 매일 밤 내 데이터베이스의 스냅 샷을 만듭니다. 그것은 오랜 시간이 걸리며 (6 시간) 비싸다. 내 자신의 변경 기반 백업을 롤링하지 않고도 (나는 그렇게 무서워 할 것입니다), 내 데이터가 실패로부터 안전하다는 것을 확인하기위한 최선의 선택은 무엇입니까?appengine 데이터 스토어 백업 권장 전략

추신 : 나는 Google 데이터가 아마 내 방식보다 안전하다는 것을 알고 있습니다. 그러나 언젠가 내가 실수로 그것을 모두 삭제하는 프로그램을 작성한다면 어떨까요?

+0

마지막 질문에 [776] (http://code.google.com/p/googleappengine/issues/detail?id=776) –

답변

3

나는 모든 선택 사항을 거의 파악했다고 생각합니다.

  1. 데이터를 잃어 버리지 않도록 Google에 알리고 실수로 데이터를 삭제하도록하지 않았 으면합니다.
  2. 엄청나게 비싼 경우 밤에 한 번만 수행하는 것보다 덜 자주 download_data으로 전체 백업을 수행하십시오.
  3. 증분 백업 솔루션을 롤백하십시오.

옵션 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 
관련 문제