2016-12-03 3 views
1

그래서 데이터 저장소에서 업데이트해야하는 값이 있습니다. 나는 아래와 같이 트랜잭션을 사용하고있다. 업데이트가 커밋 된 후에 클라이언트에 결과를 보내서 업데이트가 완료되었음을 알려줍니다. 그런 다음 클라이언트는 업데이트 된 항목 목록에 대한 다른 요청을 보냅니다. 내가 말할 수있는 한 모든 코드가 올바르게 실행되고 오류가 발생하지 않으며 결국 예상대로 업데이트 요청을 표시합니다.Google App Engine Datastore가 몇 초 전에 업데이트되기 전에 반환

내 문제는 커밋 후에도 가끔 때로는 반환 된 목록에 업데이트가 표시되는 데 몇 초 정도 걸립니다. 그것이 진절머리가 나는 연기 일 뿐이라면 그 이상입니다. 목록은이 기간 동안 올바르지 않거나 업데이트되지 않은 값을 반환합니다. 나는이 아키텍처에서 지연이있을 수 있음을 이해하지만 트랜잭션의 전체 지점은 트랜잭션이 원하는 항목을 가져 왔을 때 어떤 것이 업데이트 된 경우 이전 값을 읽을 수 없다고 생각했습니다. 오래되고 오랜 시간 동안 오래된 가치를 보지 못한 것은 잘못된 것 같습니다. 트랜잭션이 커밋되었다고 말할 때까지 기다리는 시간이 훨씬 줄어들고 전체 300ms + RTT를 가졌지 만 가정 된 후에도 몇 초 동안 여전히 나쁜 값을 얻게됩니다. 내가 여기서 무엇을 놓치고 있니?

/* 
    We don't actually delete a post, we simply replace it with a [removed] 
    version of itself. 
*/ 
router.delete('/', function (req, res) { 

    //Check our parameters 
    if (req.body == null || req.body["Thread"] == null || typeof req.body["Thread"] !== "string") { 
     res.json({ success: false, message: "Thread name was not included as a parameter.", data: null}); 
     return; 
    } 

    if (req.body == null || req.body["PostNumber"] == null) { 
     res.json({ success: false, message: "Post Number was not included as a parameter.", data: null }); 
     return; 
    } 

    if ((parseInt(req.body["PostNumber"]) || 0) < 1) { 
     res.json({ success: false, message: "Post Number was not a valid numeric value.", data: null }); 
     return; 
    } 

    var transaction = datastore.transaction(); 
    transaction.get(datastore.key(['Post', PostName(req.body["Thread"], 6, parseInt(req.body["PostNumber"]))]), function (err, value) { 

     if (err) 
     { 
      res.json({ success: false, message: "Transaction failed.", data: null }); 
      return; 
     } 

     if (value === null) 
     { 
      res.json({ success: false, message: "Post and thread combination does not exist.", data: null }); 
      return; 
     } 

     value.data.CreatorName = "[removed]"; 
     value.data.CreatorFooter = ""; 
     value.data.Contents = "[removed]"; 
     transaction.save(value); 
     transaction.commit(function (err) { 
      if (err) 
      { 
       res.json({ success: false, message: "Transaction failed.", data: null }); 
      } 
      else 
      { 
       res.json({ success: true, message: "Erased post information from table", data: null }); 
      } 
     }); 
    }); 
}); 
+0

당신이 그것을 극복하는 방법을 모른다면 그것은 매우 성가신 일입니다. 어쩌면이 문서들이 도움이 될지도 모른다. https://cloud.google.com/datastore/docs/articles/balancing-strong-and-eventual-consistency-with-google-cloud-datastore/ - https://dzone.com/articles/better-explaining-cap -정리 –

답변

3

"궁극적 인 일관성"이라고 불리는 것은 Cloud Datastore 아키텍처의 중요한 부분입니다. 데이터 저장소가 없으면 모든 요청에 ​​대해 데이터 저장소가 훨씬 느려집니다.

모든 get 작업은 항상 일관성이 있으며 모든 인덱스를 업데이트하는 데 시간이 걸리므로 쿼리에만 영향을줍니다. 색인을 업데이트하는 데 몇 초 정도 걸릴 수 있습니다.

최종 일관성을 유지하는 데는 몇 가지 전략이 있지만 클라이언트 응용 프로그램에 업데이트 된 데이터가 이므로 이미 적용/필요하지 않습니다. 저장 요청을 시작한 것은 클라이언트 앱이었습니다. 거의 모든 상황에서 데이터를 다시로드하지 않아도된다는 의미입니다.

예를 들어 앱에 17 개의 레코드 목록이 표시되고 사용자가 새 레코드를 추가 한 경우 백엔드가 저장 요청에 응답 한 후 새 레코드 개체를 표시된 목록에 추가하기 만하면됩니다. 이러한 응답에는 저장된 레코드에서 누락 된 데이터가 포함될 수 있습니다. 데이터 저장소 ID 일부 상황에서는 서버 측에서 업데이트 된 많은 속성이있는 경우 저장된 개체 전체를 반환하는 것이 더 쉬울 수도 있습니다.

매우 드문 경우이지만 개체를 ​​저장할 때 클라이언트가 업데이트 된 개체를 포함 할 수있는 전혀 새로운 데이터 집합을로드해야하는 경우에도 클라이언트는 쿼리에서 반환 된 개체를 업데이트 된 개체로 바꿀 수 있습니다. 만약 그것이 없다면. 다시 말하지만 쿼리 결과가 도착할 때까지 이미 "개체 저장"응답에서 전체 업데이트 된 개체가 있습니다.