Go#6이 있는 DynamoDB - 트랜잭션이 있는 레거시 ID 매핑

9821 단어 dynamodbgoaws
나는 지난 회가 끝날 때 너희들에게 우리가 토론한 문제를 어떻게 다른 방식으로 처리하는지 보여주겠다고 약속했다.만약 네가 이 회를 충분히 이용하고 싶다면, 나는 네가 먼저 5회를 읽는 것을 강력히 건의한다.요컨대, 해결해야 할 문제는 기존의 유류 시스템의 ID를 자신의 ids 모드를 사용하는 새로운 시스템에 비추는 것이다.

Previous approach
이 문제의 초기 해결 방안은 남겨진 id에 새 id를 생성하고 DB에 비추는 것입니다.조건에 의하면, 만약 남겨진 id에 대한 맵이 존재한다면, 우리는 이렇게 하기를 원하지 않습니다.조건이 성공했을 때, 우리는 주어진 남겨진 id가 아직 비치지 않았고, 비치는 다이나믹 DB에 삽입되었다는 것을 안다.그러나 조건이 실패하면 맵이 존재한다는 것을 알고 데이터베이스에서 가져와야 합니다.
이런 방법은 데이터 경쟁의 영향을 받지 않고 매우 잘 일한다.주어진 id를 처음으로 호출하기 위해서 Map 함수를 호출할 때, 다이나마이트에 대한 호출이 필요합니다.조건이 성공하면 새로 생성된 id를 되돌려줍니다. 단, 같은 id를 사용하여 Map 후속 호출을 하려면 데이터베이스에 두 번 호출해야 합니다.첫 번째는 우리의 조건 때문에 실패한 호출이고, 두 번째는 다이나모에서 이미 존재하는 새로운 id를 가져옵니다.

ReturnValues parameter
사실이 증명하듯이 PutItem 중의 매개 변수는 ReturnValues라고 한다.기본값NONE 또는 ALL_OLD로 설정할 수 있습니다.ALL_OLDPutItem가 항목을 덮어쓰면 다이나마이트에서 온 응답이 덮어쓰기 전에 내용을 포함한다는 것을 나타낸다.이것은 우리에게 있어서 매우 좋다.우리는 만약 우리가 실패한다면, 무엇이 실패를 초래했는지 알고 싶다.이것은 우리가 두 번째로 디나모에게 전화할 필요가 없다는 것을 의미한다.
불행하게도 PutItem 성공하고 조건 검사에 실패한 경우 PutItem 실패하기 전에 프로젝트의 이미지를 얻을 수 없을 때만 유효합니다.
이것은 작용하지 않기 때문이다. 아마도 우리가 얻은 조건 실패에 대한 오류는 왜 실패했는지에 대한 상하문을 더 많이 포함하고 있을 것이다.
불행히도 사실은 그렇지 않다.
그러나 우리는 다른 곳에서 이 아이디어를 사용해서 우리가 원하는 것을 얻을 수 있다.

Transactions
일반적으로 거래는 다른 목적을 위한 것이다.데이터베이스 상태에 대한 많은 변경이 필요하고 모든 변경이 성공해야만 업무를 완성할 수 있을 때 사용할 수 있습니다.만약 업무 중의 변경 사항이 실패하면 전체 업무가 실패하고 아무런 변경도 하지 않습니다.
트랜잭션이 실패하면 DynamoDB는 어떤 일이 일어났는지 더 많은 상하문을 제공할 수 있습니다.그것이 어떻게 일을 하는지 우리에게 보여 주시오.

Code
모든 코드는 5회 코드와 같다.유일하게 변경된 기능은 Map 기능입니다.여기서는 행위만 검증하는 자동화 테스트의 묘미를 볼 수 있다.우리는 마음대로 변경할 수 있어, 테스트는 전혀 변경할 필요가 없다.그 밖에 그들은 우리에게 새로운 방법이 효과가 있는지의 여부를 알려줄 것이다.
사무를 사용하기 위해 Map 함수를 변경합시다.
idsMapping := mapping{OldID: old, NewID: uuid.New().String()}
attrs, err := dynamodbattribute.MarshalMap(&idsMapping)
if err != nil {
  return "", err
}
expr, err := expression.NewBuilder().
  WithCondition(expression.AttributeNotExists(expression.Name("old_id"))).
  Build()
if err != nil {
  return "", err
}
내가 너에게 Map개의 기능만 바뀌었다고 말했을 때, 나는 결코 전부를 가리키는 것이 아니다.시작이 똑같다.간단하게 돌이켜 보면, 우리가 생성한 낡은 id와 새 id를 사용하여 맵을 만듭니다.그리고 우리가 이미 존재하는 항목을 놓으려고 할 때, 우리는 실패의 조건을 만들었다.
_, err = m.db.TransactWriteItemsWithContext(ctx, &dynamodb.TransactWriteItemsInput{
  TransactItems: []*dynamodb.TransactWriteItem{
    {
      Put: &dynamodb.Put{
        ConditionExpression:                 expr.Condition(),
        ExpressionAttributeNames:            expr.Names(),
        ExpressionAttributeValues:           expr.Values(),
        Item:                                attrs,
        ReturnValuesOnConditionCheckFailure: aws.String("ALL_OLD"),
        TableName:                           aws.String(m.table),
      },
    },
  },
})
여기 주문서Put가 조작된 거래가 있습니다.일반적인 PutItem 방법인 ReturnValuesOnConditionCheckFailure 매개 변수의 옵션이 아닌 것도 있다.조건이 실패할 때, 우리가 원하는, 즉 이미 존재하는 새로운 id를 얻을 수 있기를 바랍니다.
이곳의 관건은 잘못된 처리다.
if err == nil {
  return idsMapping.NewID, nil
}
오류가 없으면 조건이 성공했다는 것을 의미합니다. 따라서 주어진 유류 id 호출 Map 을 사용한 것은 이번이 처음입니다. 다이나마이드에 입력한 내용만 되돌려줍니다.
aerr, ok := err.(*dynamodb.TransactionCanceledException)
if !ok {
  return "", err
}
만약 오류가 있다면, 우리는 그것의 유형을 검사해야 한다. 만약 TransactionCanceledException 그렇지 않다면, 문제가 생겼을 것이다. 우리는 그것이 무엇인지 모르기 때문에, 우리는 되돌아갈 뿐이다.
return aws.StringValue(aerr.CancellationReasons[0].Item["new_id"].S), nil
그렇지 않으면 new_id로부터 CancellationReasons를 받을 수 있습니다. 우리는 그것을 고객에게 되돌려줄 수 있습니다. 디나모에게 다시 전화할 필요가 없습니다!

Summary
DynamoDB API를 사용하여 트랜잭션이 실패한 이유를 설명하는 방법을 방금 설명했습니다.예를 들어 DynamoDB에 새로운 맵을 삽입하거나 기존 맵을 한꺼번에 얻을 수 있음을 의미합니다.
당신은 반드시 이런 방법을 사용해야 합니까?저번보다 좋아요?이것은 상황을 보고 결정해야 한다.DynamoDB를 한 번만 호출할 때 요청/응답 왕복 시간을 절약할 수 있습니다.그것은 공짜입니까?절대 아니야.당신이 지불할 용량 단위로 말하자면, 다이나모FB의 업무 호출은 더욱 비싸다.따라서 이러한 특수한 상황에서 DynamoDB 사무 호출에 더 많은 비용을 지불하든지, 보통 더 적은 호출을 하든지, 한 호출에 더 적은 비용을 지불하든지, 여러 번 DynamoDB를 호출하든지, 그리고 DynamoDB의 네트워크 호출을 기다리는 데 더 많은 시간을 들일 것이다.그럼에도 불구하고 나는 어떤 방법도 추천하지 않는다.이것은 너의 필요에 달려 있다.나는 단지 가능한 선택을 보여주고 있을 뿐이다.

좋은 웹페이지 즐겨찾기