AWS

[AWS] aws 강의 섹션 22 (Dynamo DB)

대기업 가고 싶은 공돌이 2024. 11. 5. 20:48

기존의 RDS의 문제점

 

  • 더 좋은 성능의 데이터베이스를 원한다고 했을 때 RDS는 수직적 스케일링밖에 하지 못 한다.
    • 물론 수평적 스케일링도 가능하지만, 읽기 전용 복제본을 만들어 부하를 분산 시키는 방법 밖엔 없다.
    • RDS에는 수평적 쓰기 스케일링은 존재하지 않는다.
  • 이러한 문제점을 해결하기 위해 NoSQL 데이터베이스가 나타났다. (DynamoDB)

NOSQL Database

  • NoSql은 수평적 확장성을 갖는다.
  • 유명한 기술로는 몽고 디비와 다이나모 디비가 있다.
  • 그러나 지원되지 않는 쿼리문이 굉장히 많다.
  • sum, avg 같은 집계 연산이나 쿼리문이 지원되지 않기 때문에, 수평 확장성을 갖는다.

Amazon DynamoDB

  • 고 가용성의 NoSQL 데이터베이스이다.
  • 여러 가용 영역에 걸쳐 즉시 복제가 가능하다.
  • 항상 빠른 성능을 보장한다. 일관성 있게 빠르다.
    • 검색 시 지연 시간이 낮고, AWS 서비스 이기 때문에 IAM과 완전히 통합되어 보안, 권한 부여 등이 가능하다.
  • 비용이 저렴하고 오토 스케일링 기능이 있다.

DynamoDB - Basics

  • 테이블로 구성되며, 각 테이블은 기본 키를 가져야 한다.
  • 각 테이블은 item이라는 행을 무한대로 가질 수 있다.
    • 아이템의 최대 크기는 400KB 이다.
  • 각 item은 속성을 가지고 있다. 속성은 테이블의 열과 비슷하다.
    • 속성은 시간이 지나도 추가할 수 있다.
  • 테이블을 만들 때 모든 것을 정의할 필요가 없다. 
  • 지원되는 데이터 타입은
    • String, Number, Binary, Boolean, Null
    • List, Map
    • String Set, Number Set, Binary Set 이 있다.

DynamoDB - 기본 키

  • 기본 키에는 두 개의 옵션이 있다.
  • 첫 번째는 파티션 키 (Hash)
    • 키가 아이템 별로 고유해야 한다.
    • 따라서 키는 매우 다양해야 한다. 분산에 대비해서

  • 두 번재 옵션은 파티션 키 + sort 키 (Hash + Range)
    • 각각의 item 마다 두 키의 조합이 반드시 고유해야 한다.
    • 데이터는 파티션 키에 의해 그룹으로 묶인다.
    • 예를 들어, 유저 아이디를 파티션 키로, 유저의 게임 수행 아이디를 정렬 키로 선택하면
      • 유저 별로 묶어서, 게임 판 수마다의 정보를 확인할 수 있다.

DynamoDB - 읽기/ 쓰기 용량

  • 테이블의 읽기와 쓰기의 처리량을 조절할 수 있다. 사전에 설정해두어야 한다.
  • Provisioned Mode(default)
    • 초당 읽기와 쓰기 용량을 지정해야 한다.
    • 사전에 용량을 미리 설정해야 한다.
    • 설정한 용량만큼, 매 시간 비용을 지불하게 된다.
  • On-Demant Mode
    • 작업량을 기반으로, 읽기와 쓰기를 자동으로 스케일 업, 다운 한다.
    • 사용한 만큼 비용을 지불하나, 프로비전 모드 보다는 훨씬 비싸다.
  • 24 시간마다, 프로비저닝 모드와 온디맨드 모드를 바꿀 수 있다.

RW Capacity Modes - Provisioned

  • 읽기 쓰기 용량을 프로비저닝 해야한다.
  • RCU (Read Capacity Units) - 읽기 처리량을 뜻한다.
  • WCU (Write Capacity Units) - 쓰기 처리량을 의미한다.
  • 수요를 맞추기 위해서, 처리량을 오토 스케일링하는 옵션이 있다.
  • 만약 사전 정의된 사용량보다, 더 많은 처리량이 들어올 경우도 괜찮다.
    • 버스트  모드가 있어서 일시적으로 처리 가능하다.
    • 만약 버스트 모드의 용량을 다 쓴 경우 프로비저닝 처리량 초과 예외가 발생한다.
    • 지수 백오프 전략을 사용해서 작업을 다시 시도해야 한다.

DynamoDB - WCU

  • 1 WCU란, 초당 1KB의 아이템을 쓸 수 있다는 것이다.
  • 그래서 아이템이 만약 2KB라면, 우리는 프로비저닝 할 때 2 WCU를 설정해야 한다.
  • 문제 예시를 들어보자, 초당 10개의 아이템이 적히고, 아이템은 개당 2KB라고 한다면 몇의 WCU가 필요할까?
    • 정답은 20 WCU이다.

  • 계산 방법이 참 이상한데, 한 아이템이 4.5 KB이고 초당 6개의 아이템이 적힌다고 하면
    • 한 아이템을 적는 데 필요한 WCU는 항상 반올림 되어 계산 된다고 한다.
    • 즉, 4.5KB는 4.5 WCU가 필요한 것이므로, 5 WCU가 필요한 것이고 초당 6개의 아이템이 적히니, 30 WCU가 필요한 것이다.

DynamoDB - RCU - mode

  • Strongly Consistent Read 모드와
  • Eventually Consistent Read 모드 두 가지가 있다.

  • 다이나모 디비는 실제론 다음과 같이 여러 대의 서버로 이뤄져 있다.
  • 여기서 문제가 발생하는데 바로 동기화 문제다.
  • 만약 서버1에 데이터를 작성하고, 바로 서버2에서 읽기가 수행된다면, 오래된 데이터를 읽을 가능성이 있는 것이다.
  • 이것 때문에 두 가지 모드가 존재한다.
    • 첫 번째는 Eventually Consistent Read (Default) 모드로, 오래된 데이터를 읽을 가능성이 존재하는 모드다.
    • 두 번째는 Strongly Consistent Read 모드로 항상 정확한 데이터를 읽어온다.
      • ConsistentRead라는 매개변수를 참으로 두어서 API를 호출해야 사용할 수 있다.
      • RCU를 두 번 소모하기 때문에 더 비용이 비싸다. 물론 지연시간도

DynamoDB - RCU

  • 읽기 용량 유닛은 초당 크기가 4KB인 아이템을 올릴 수 있다.
    • 강력한 일관된 읽기 모드라면 초당 4KB 읽기 가능
    • 그냥 읽기 모드라면 초덩 8KB를 읽을 수 있다.
  • 예를 들어, 10 개의 강력한 일관된 읽기 모드 요청이 들어왔고 아이템 별 사이즈는 4KB 이다.
    • 즉, 40KB 인데 강력한 일관된 읽기 모드이므로 10RCU가 필요하다.
  • 예를 들어, 16개의 최종 그냥 읽기 모드 요청이 들어왔고 아이템 별 사이즈는 12KB라면
    • 192KB가 나오고 초당 8KB를 읽을 수 있으므로, 24 RCU가 필요하다. 
  • 마지막으로, 이것도 반올림이 필요하다.
  • 만약, 10 개의 강력한 일관된 읽기 모드에서 아이템 별 사이즈가 6KB라면
  • 초당 4KB를 읽을 수 있으므로, 아이템당 1.5 RCU 즉 2RCU가 되어, 20RCU가 필요해진다.=

DynamoDB - Partitions Internal

  • 다이나모 디비는 테이블로 구성되고, 테이블에는 파티션이 존재한다.
  • 파티션은 데이터의 복사본으로 특정 서버에 존재한다.
  • 애플리케이션이 다이나모 디비에 뭔가를 쓸 때, 애플리케이션은 키와 속성을 보낼 것이다.
  • 여기서 파티션 키로, 해싱 알고리즘을 거쳐 어느 파티션에 저장되어야 할지를 판단할 수 있다.

  • 이와 같은 방식으로, 각 파티션별로 즉 서버 별로 데이터가 적절하게 분배되어 저장된다. 
  • 만약 10개의 파티션이 존재하고, 10개의 WCU, RCU가 들어왔다면
    • 각 파티션 별로 1개의 WCU, RCU가 적절하게 분배된다는 것만 알면 된다.

DynamoDB - Throttling

  • 파티션 레벨에서, WCU, RCU의 초과가 일어나면 프로비저닝 처리량 초과 예외가 발생한다.
    • 하나의 파티션 키가, 핫키여서 해당 파티션에 많은 부하가 쏠릴 수 있다.
    • 핫 키 예시 말고도, 하나의 아이템이 너무 큰 경우에도 예외가 발생할 수 있다.
  • 예외 발생 시 해결 방법
    • 지수 백오프를 하는 것이다. (SDK를 사용하고 있다면, 이미 적용되어있다.)
    • 파티션 키를 최대한 많이 분산 시키는 것이다.
    • 하나의 파티션을 집중적으로 읽어서 RCU이슈가 생긴 상황이라면 DtnamoDb Accelerator 라는 기능을 사용해야한다

R/W Capacity Modes - On demand

  • 작업량에 따라, 자동으로 스케일 업 다운이 이뤄진다.
  • WCU, RCU를 미리 예약할 필요 없다.
  • 2.5 배 더 비싸다.
  • 실제로 사용한 읽기와 쓰기에 대해 비용이 청구되기에 다른 단위가 쓰인다.
  • Read Request Units (RRU) - 읽기의 처리량
  • Write Request Units (WRU) - 쓰기 처리량
  • 연산은 동일하나 실제 사용한 요청만을 기반으로 비용이 처리된다.

DynamoDB - Writing Data

데이터베이스에 데이터를 작성할 때 선택할 수 있는 몇 가지 모드가 존재한다.

  • Plutltem
    • 기본 키가 같은 항목이 있다면 새 항목으로 완전히 교체한다.
    • WCU를 소모한다.
  • UpdateItem
    • 기존 항목의 속성을 바꾸거나, 기존 항목이 존재하지 않는다면, 새 항목을 추가한다.
  • Conditional Writes
    • 조건이 충족되었을 때에만, 쓰기/ 업데이트/ 삭제가 이뤄진다. 
    • 여러 아이템에 동시 접근하는 데 유용하다.

DynamoDB - Reading Data

  • GetItem
    • 기본 키를 기반으로 아이템을 가져온다.
    • 기본 키는 해시 키 또는 해시 키 + 범위 키 둘 중 하나다.
    • 읽어 오는 모드도 두 개가 존재한다.
      • Eventually Consistent Read 모드 (default)
      • Strongly Consistend Reads (more RCU)
    • ProjectionExpression Api를 통해 특정 속성 몇 가지를 설정해 해당 속성 데이터만 가져올 수도 있다.

DynamoDB - Reading Data (Query)

  • Query returns items based on:
    • KeyConditionExpression
      • 파티션 키에, = 연산자를 사용해 동일한 항목을 반환한다.
      • sort 키에 등호 연산자를 사용한 항목 반환도 가능하다. (이는 선택 사항이다.)
    • FilterExpression
      • 쿼리 작업이 완료된 후 데이터가 반환되기 이전에 필터링을 추가한다.
      • 기본 키가 아닌 속성에 필터링을 가할 수 있다.
    • Limit 파라미터를 사용해 가져올 항목의 수를 제한할 수도 있다.
    • 항목 수 제한에 도달하거나, 1MB에 도달할 때 강제로 반환 된다.
    • 더 많은 데이터를 가져오고 싶으면 페이징 기법을 써야한다.
    • 보조 인덱스를 사용 가능하다.

DynamoDB - Reading Data (Scan)

  • 쿼리가 특정 파티션 키 데이터를 읽어온다면, scan은 테이블 전체의 데이터를 읽어온다.
  • 필터링도 가능하지만, 클라이언트 사이드에서만 된다. 즉, 효율이 좋지 못 하다.
  • 스캔은 전체 데이터를 내보내는데, 최대 1Mb의 데이터만을 내보낼 수 있다.
    • 마찬가지로 더 많은 데이터를 읽고 싶다면, 페이징 기술을 사용해야 한다.
  • 아주 많은 양의 RCU를 사용한다.
    • 따라서 다른 작업에 영향을 끼치게 하고 싶지 않으면 Limit을 스캔에 적용하거나, 
      결과 사이즈를 줄여햐 한다.
  • 더 빠른 성능을 원한다면, 병렬 스캔을 사용하면 된다. 
    • 병렬 스캔을 통해, 여러 개의 세그먼트를 동시에 스캔한다.
    • 물론 사용되는 처리량과 RCU는 늘어난다.
  • ProjectionExpression, filterExpression 과 같이 사용할 수 있다.

DynamoDB - Deleting Data

  • DeleteItem
    • 개별 항목 삭제 시 사용하며
    • 조건부 삭제도 가능하다
  • Delete table
    • 테이블의 모든 것을 삭제한다.
    • 테이블 전체와 테이블의 항목을 삭제하며 scan을 활용한 삭제보다 속도가 빠르다
    • 전부 삭제하려면 scan을 통한 삭제말고 Delete Tabla APi를 사용하도록 하자

DynamoDB - Deleting Data

  • 일괄로 작업을 처리하여 API호출 수를 줄이고 효율을 높일 수 있다.
  • 배치 작업에 속한 모든 작업은 다이나모 디비를 통해 병렬로 적용되어, 효율성을 높인다.
  • 일부 작업이 실패할 수도 있으나, 실패한 항목이 리턴되므로, 해당 항목만 다시 시도할 수 있다.
  • BatchWritenItem
    • 호출 한 번으로 최대 25번의 Putltem과 DeleteItem 작업을 수행할 수 있다.
    • 초당 16MB의 데이터를 기록할 수 있으며, 항목마다 400KB의 제한이 똑같이 적용된다.
    • 업데이트 작업은 배치로 불가능 하다.
    • 쓰기 용량이 부족한 경우, UnprcessedItems라는 것이 반환되며,
      특정 항목을 다시 시도할 수 있다.
      • 지수 백오프 방식을 사용하던지, 실패 아이템을 받아 WCU양을 늘려 재시도를 할 수도 있다.
  • BatchGetItem
    • 하나 이상의 테이블에서 항목이 반환되며, 최대 100개의 항목과 16GB의 데이터를 받을 수 있다.
    • 모든 항목을 병렬로 가져온다.
    • 일부 항목이 누락될 경우, 용량이 부족해서 읽기 작업에 실패하고, UnprocessedKeys가 
      리턴되는 경우도 흐름은 똑같다.
    • 지수 백오프로 다시 시도하던지, 읽기 용량을 추가해 다시 시도하던지 하면 된다. 

DynamoDB - PartiQl

  • 특정 작업을 수행하기 위한 API 호출이 있지만, 때로는 직접 SQL을 사용해야할 때가 있다.
  • PartiQl을 사용하면 SQL을 사용해서 데이터를 선택, 삽입, 업데이트, 삭제할 수 있다.
    • 하지만 조인은 지원하지 않는다.
  • AWS Management Console
  • NoSQL Workbench
  • DynamoDb APi
  • AWS CLI
  • AWS SDK
  • 등에서 PartiQl을 사용할 수 있다.