Category: Amazon DynamoDB


Amazon DynamoDB에 대한 VPC 엔드포인트 추가

오늘부터 Amazon DynamoDB에 대한 Amazon Virtual Private Cloud (VPC)  엔드 포인트를 (서울 리전 포함) 모든 AWS 리전에서 사용할 수 있습니다. AWS 관리 콘솔 또는 AWS 명령줄 인터페이스 (CLI)를 사용하여 즉시 엔드 포인트를 프로비저닝 할 수 있습니다. DynamoDB의 VPC 엔드 포인트 사용에는 추가 비용이 들지 않습니다.

AWS 고객은 각자 자원에 대한 통신 보안 또는 외부 격리가 필요한 이유로 Amazon VPC (Virtual Private Cloud) 내에서 애플리케이션을 실행합니다. 이전에는 VPC내 EC2 인스턴스가 DynamoDB에 접속하려면 두 가지 옵션이 있었습니다.

먼저 인터넷 게이트웨이 (NAT 게이트웨이 또는 인스턴스 공용 IP 할당)를 사용하거나 VPN 또는 AWS Direct Connect를 통해 로컬 인프라로 모든 트래픽을 라우팅 한 다음 DynamoDB로 다시 라우팅 할 수 있습니다. 이러한 솔루션은 데이터 보안 및 네트워크 처리량에 영향을 미치기 때문에 NACL 또는 보안 그룹을 구성하여 DynamoDB에 대한 접근만 제한 할 수 있습니다. 아래 그림은 이러한 이전 방식의 아키텍처 입니다.

엔드 포인트 만들기

이제 DynamoDB에 대한 VPC 엔드포인트를 만들어 보겠습니다. DescribeVpcEndpointServices API 호출로 지원 여부를 알 수 있습니다.

Bash

aws ec2 describe-vpc-endpoint-services --region ap-northeast-2
{
    "ServiceNames": [
        "com.amazonaws.ap-northeast-2.dynamodb",
        "com.amazonaws.ap-northeast-2.s3"
    ]
}

다양한 API를 사용하여, 엔드포인트 설정도 가능합니다.

이제 콘솔 사용 방법을 알려 드리겠습니다. 먼저 VPC 콘솔로 이동하여, 사이드 바에서 “Endpoints”를 선택합니다. 거기에서 “Create Endpoint”를 클릭하면 됩니다.

엔드포인트에 대한 AWS Identity and Access Management (IAM) 정책 섹션을 확인할 수 있습니다. 이는 일반 IAM 정책에서 DynamoDB가 지원하는 모든 세분화된 접근 제어를 지원하며 IAM 정책 조건에 따라 접속을 제한 할 수 있습니다.

현재 VPC 내 인스턴스에 대한 전체 접속 권한을 부여하고 “Next Step”를 클릭하십시오.

이를 통해 VPC 경로 테이블 목록을 가져오고, 경로 테이블 중 어느 쪽에 내 엔드포인트를 할당할지 선택하고 “Create Endpoint”를 선택합니다.

콘솔에서 나오는 경고 메시지에서 공용 IP 주소를 기반으로 DynamoDB에 대한 소스 제한 사항이 있는 경우, DynamoDB에 접근하는 인스턴스의 소스 IP가 사설 IP 주소가됩니다

DynamoDB 용 VPC Endpoint를 VPC에 추가 한 후,  아키텍처는 아래와 같이 단순화 됩니다.

진짜 간단하게 끝낼 수 있습니다. 오늘 부터 바로 사용 가능하며 더 자세한 사항은 기술 문서를 참고하시기 바랍니다.

– Randall;

이 글은 New – VPC Endpoints for DynamoDB의 한국어 번역입니다.

MySQL에서 다운타임 거의 없이 DynamoDB로 마이그레이션하기

많은 고객들이 MySQL 과 같은 관계형 데이터베이스에서 Amazon DynamoDB으로 마이그레이션 하고자 합니다. 왜냐하면, 완전 관리형, 고성능, 높은 확장성과 유연성을 갖춘 NoSQL 데이터베이스 서비스이기 때문입니다.  DynamoDB의 경우, 트래픽 및 비즈니스 요구 사항에 따라 용량을 유연하게 증가 및 감소시킬 수 있기 때문에 서비스에 필요한 총 비용을 기존의 서버 기반의 RDBMS보다 더 쉽게 최적화 하는 것이 가능합니다.

하지만, 마이그레이션 작업은 통상적으로 다음과 같은 두 가지 이슈가 있을 수 있습니다:

  • 고객서비스가 반드시 24/7/365 가용 해야 할 경우 다운타임으로 인한 서비스 중단을 어떻게 최소화할 것인가?
  • RDBMS와 DynamoDB의 서로 다른 Key Design을 어떻게 반영할 것인가?

이 글에서는 다운타임을 최소화하면서 MySQL의 주요 DB 디자인을 NoSQL에 적합한 형태로 변환한 후,  MySQL의 기존 데이터를 DynamoDB로 원활하게 마이그레이션하는 두 가지 방법을 소개합니다.

마이그레이션을 위한 AWS 서비스 빌딩 블록
이 글에서 포함된 예제 코드들은 다음 AWS 서비스을 사용합니다:

  • AWS 데이터 마이그레이션 서비스(AWS DMS) 는 가장 범용적으로 사용되는 상용 및 오픈소스 데이터베이스 사이의 데이터 마이그레이션을 가능하게 해줍니다. AWS DMS는 서로 다른 데이터베이스 플랫폼 간의 동종 및 이종 데이터 마이그레이션을 지원합니다.
  • Amazon EMR은 방대한 양의 데이터를 신속하게 처리할 수 있도록 하는 관리형 Hadoop 프레임워크입니다. Hive 및 다른 비지니스 소프트웨어를 포함하는 이미 설정된 소프트웨어 스택들로 구성된 EMR 클러스터를 손쉽게 구축할 수 있습니다.
  • Amazon Kinesis는 실시간 트랜잭션, 로그 데이터, 클릭 스트림과 같은 방대한 양의 실시간 데이터를 최대 7일까지 지속적으로 저장하고 유지할 수 있습니다.
  • AWS Lambda는 서버를 준비하거나 운영하지 않고, 원하는 코드를 클라우드 상에서 직접 실행할 수 있도록 해 줍니다. AWS Lambda에서 실행되는 코드는 Amazon Kinesis Stream과 같은 다른 AWS 서비스들에 의해 자동으로 호출되도록 설정할 수 있습니다.

마이그레이션 방안

이 글에서는 다음 두가지 데이터 마이그레이션 옵션을 설명합니다.

  1.  AWS DMS 사용: AWS DMS는 DynamoDB 테이블을 타겟으로 마이그레이션을 지원합니다. 객체 매핑을 사용하여 마이그레이션 과정 중에 원본 데이터를 DynamoDB에서 요구하는 데이터 구조에 적합하게 재구성하는 것이 가능합니다.
  2. Amazon EMR, Kinesis 및 AWS Lambda 커스텀 스크립트 사용: 보다 복잡한 변환 과정 및 유연성이 요구될 때는 EMR, Kinesis, Lambda를 이용한 마이그레이션을 고려할 수 있습니다. MySQL 레코드를 더 적은 DynamoDB 항목으로 그룹화하고, 속성 이름을 동적으로 결정하고, 마이그레이션 중에 프로그래밍 방식으로 비즈니스 로직을 추가하고, 더 많은 데이터 유형을 지원하거나 하나의 큰 테이블에 대해 병렬 제어를 추가하려면 세분화된 사용자 제어가 필요합니다.

데이터 초기 적재 및 벌크 입력을 완료한 후에 가장 최근의 실시간 데이터를 CDC(Change Data Capture)로 처리하고 나면 최종적으로 애플리케이션이 DynamoDB를 바라보도록 설정을 변경하게 됩니다.

이 접근방법에서 변경데이터를 캡처하는 방법에 대한 상세한 내용은 AWS 데이터베이스 블로그 포스팅의 Streaming Changes in a Database with Amazon Kinesis에서 다루고 있습니다. 이 블로그 포스팅에서 사용한 모든 코드 및 테스트 코드는 big-data-blog GitHub 저장소를 통해 얻을 수 있습니다.

마이그레이션 솔루션 아키텍쳐

두 접근 방법의 전반적인 아키텍처는 다음과 같습니다.

방안 1:  AWS DMS 사용

이 절에서는 DMS를 이용하여 어떻게 MySQL 데이터베이스에 접속하고, 원본 데이터를 읽고, 데이터를 대상 DynamoDB 데이터베이스에 적재하기 위해 데이터를 정형화하는지에 대해 설명합니다.

1. 복제 인스턴스 생성 및 원본 및 대상 엔드포인트 설정하기

AWS Database Migration Service Best Practices를 참고하여 마이그레이션을 수행하기에 충분한 저장소와 처리능력을 갖춘 복제 인스턴스를 생성합니다. 예를 들어, 마이그레이션 대상 테이블이 많거나 동시에 여러 복제 작업을 수행할 계획이라면 더 큰 크기의 인스턴스들을 사용하는 것을 고려하여야 합니다. 데이터 복제 서비스는 상당한 양의 메모리와 CPU 리소스를 사용합니다.

MySQL 사용자 정보를 사용하여 MySQL에 접속하고 SUPER, REPLICATION CLIENT 권한으로 데이터를 추출합니다. MySQL 설정에서 Binary log를 활성화하고 CDC를 위해 binlog_format 파라미터를 ROW로 설정합니다. DMS를 사용하는 방법에 대한 더 상세한 정보는 AWS Database Migration Service 사용자 가이드의 Getting Started 문서를 참조합니다.

mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'welcome1'; mysql> GRANT all ON <database name>.* TO 'repl'@'%'; mysql> GRANT SUPER,REPLICATION CLIENT ON *.* TO 'repl'@'%';

DMS에서 DynamoDB 데이터베이스를 대상으로 설정하기 전에, DMS가 사용할 IAM Role을 생성하고 DynamoDB 대상 테이블에 접근할 권한을 부여해야 합니다. 원본 및 대상 데이터베이스에 접근할 엔드포인트들도 다음 스크린샷과 같이 설정합니다.

다음 스크린샷은 source-mysql의 상세 정보 화면입니다.

객체 매핑 규칙 설정 및 작업 생성하기

다음 예제에서는, MySQL 테이블이 복합 프라이머리 키( customer id + ordered + productid )를 가지고 있다고 가정합니다. 이와 같은 경우, 객체 매핑 규칙을 사용하여 DynamoDB에서 요구하는 데이터 구조에 적합하게 키를 재구성할 수 있습니다.

여기에서는 대상 DynamoDB 테이블은 customer idorder id 컬럼의 조합을 hash key로 설정하고 product id 컬럼을 sort key로 설정합니다. 하지만, 실제 마이그레이션 상황에서는 데이터 적재 및 접근 패턴에 따라 파티션 키를 결정해야 합니다. 보통 카디널리티가 높은 속성을 파티션키로 사용하게 됩니다. DynamoDB에서 올바른 파티션 키를 결정하는 방법에 대한 상세한 내용은 Choosing the Right DynamoDB Partition Key 블로그를 참조하십시오.

여기서 rule-action을 map-record-to-record로 설정하였고 해당 컬럼을 제외 대상 컬럼(exclude-columns) 속성 리스트에 포함시키지 않았기 때문에, DMS 서비스는 원본 데이터의 quantity 컬럼을 대상 DynamoDB 테이블에 자동으로 생성합니다. map-record-to-recordmap-record-to-document 설정에 대한 상세 내용은 AWS Database Migration Service에서 Amazon DynamoDB 데이터베이스를 대상으로 사용 문서를 참조하십시오.

마이그레이션은 작업 생성시 Start task on create 옵션을 해제하지 않을 경우, 작업이 생성되는 즉시 시작됩니다. 마이그레이션 작업이 백그라운드에서 수행되는 동안 어떤 일이 발생하는지 확인하기 위하여 enabling logging을 선택하는 것을 추천합니다.

다음 스크린샷은 작업 생성 페이지를 보여줍니다.

콘솔에서 마이그레이션 개별 데이터베이스 테이블과 마이그레이션에 필요한 변환을 포함한 스키마를 지정할 수 있습니다. Guided 탭의 Where 항목에서 스키마, 테이블을 설정하고 Action 항목에서 포함/불포함 여부를 설정합니다. Filter 항목에서 테이블 내의 컬럼명 및 적용할 조건을 설정합니다.

테이블 매핑 정보는 JSON 형태로 생성할 수도 있습니다. JSON 탭에서 Enable JSON editing 체크박스를 선택하십시오.

다음은 원본데이터가 대상 테이블의 어디에 위치할지 결정하는 객체 매핑 규칙에 대한 예제입니다. 아래 예제를 복사하여 사용할 경우, 아래 속성들을 실제 사용하는 값으로 변경해야 합니다. 보다 많은 예제들은 AWS Database Migration Service에서 Amazon DynamoDB 데이터베이스를 대상으로 사용 문서를 참조하십시오.

  • schema-name
  • table-name
  • target-table-name
  • mapping-parameters
  • attribute-mappings
{
  "rules": [
   {
      "rule-type": "selection",
      "rule-id": "1",
      "rule-name": "1",
      "object-locator": {
        "schema-name": "mydatabase",
        "table-name": "purchase"
      },
      "rule-action": "include"
    },
    {
      "rule-type": "object-mapping",
      "rule-id": "2",
      "rule-name": "2",
      "rule-action": "map-record-to-record",
      "object-locator": {
        "schema-name": "mydatabase",
        "table-name": "purchase"
 
      },
      "target-table-name": "purchase",
      "mapping-parameters": {
        "partition-key-name": "customer_orderid",
        "sort-key-name": "productid",
        "exclude-columns": [
          "customerid",
          "orderid"           
        ],
        "attribute-mappings": [
          {
            "target-attribute-name": "customer_orderid",
            "attribute-type": "scalar",
            "attribute-sub-type": "string",
            "value": "${customerid}|${orderid}"
          },
          {
            "target-attribute-name": "productid",
            "attribute-type": "scalar",
            "attribute-sub-type": "string",
            "value": "${productid}"
          }
        ]
      }
    }
  ]
}

마이그레이션 작업 시작하기
만약 target-table-name 속성에 정의된 대상 테이블이 DynamoDB에 존재하지 않을 경우, DMS는 데이터 변환 참조와 추가 주제를 포함하는 AWS Database Migration Service 참조 문서에서 설명하는 원본 데이터 형식대상 데이터 형식에  대한 데이터형 변환 규칙에 따라 테이블을 생성합니다. 마이그레이션 작업의 진행상황을 모니터링하는 많은 지표들이 제공됩니다. 보다 상세한 모니터링 관련 정보는 AWS Database Migration Service 작업 모니터링 문서에서 확인하실 수 있습니다.

다음 스크린샷은 CloudWatch Logs에 기록된 이벤트들과 오류 샘플입니다.

마이그레이션에 사용한 DMS 복제 인스턴스들은 모든 마이그레이션 작업이 완료된 후에는 삭제되어야 합니다. 보유기간이 경과한 Cloudwatch log들은 자동으로 삭제됩니다.

방안 2: EMR, Amazon Kinesis, Lambda 사용

이 절에서는 보다 정교한 제어와 유연성을 제공하기 위하여 EMR과 Amazon Kinesis, Lamdba를 사용하는 다른 방안에 대해 다룹니다. 만약 작업환경에 MySQL replica가 포함된다면, replica로부터 데이터를 마이그레이션하는 것을 추천합니다.

키 디자인 변경하기
데이터베이스를 RDBMS에서 NoSQL로 변경하기로 결정했다면, 성능 및 비용 효율성을 위해서 데이터 키를 NoSQL에 더 적합하도록 설계할 필요가 있습니다.

방안 #2에서는 방안 #1과 비슷하게 MySQL 데이터베이스 원본이 복합 프라이머리 키 (customerid + orderid + productid)를 가지고 있다고 가정합니다. 하지만, 여기서는 MySQL 레코드들을 customerid(hash key)와 orderid(sort key)를 사용하여 더 적은 DynamoDB 아이템들로 그룹화합니다. 이를 위하여, MySQL의 복합키 중 마지막 컬럼 (productid)을 복합키에서 제거하는 대신 DynamoDB의 속성 이름으로 하고, Quantity 컬럼을 해당 속성의 값으로  변환합니다.

이런 변환법을 통해 전체 아이템의 수를 줄일 수 있으며, 같은 양의 정보를 더 적은 RCU(Read Capacity Unit)을 사용하여 조회할 수 있어 비용을 절감하면서 더 나은 성능을 얻을 수 있습니다. RCU/WCU(Read Capacity Unit/Write Capacity Unit)를 어떻게 계산하는지에 대한 더 상세한 정보는 프로비저닝된 처리량 문서를 확인하시기 바랍니다.

단계별 마이그레이션

방안 #2는 다음 두 단계의 마이그레이션이 동시에 진행됩니다.:

  • 일괄 처리: MySQL 데이터 export, export파일의 S3 업로드, S3 데이터 DynamoDB에 import
  • 실시간 처리: MySQL의 변경 데이터 캡처, insert/update/delete 트랜잭션을 Kinesis Stream에 송신, DynamoDB에 데이터를 입력하기 위한 Lambda 함수 호출.

데이터의 일관성과 무결성을 유지하기 위해 데이터를 캡처하고 Amazon Kinesis Stream에 밀어넣는 작업은 일괄 처리 프로세스 전에 시작되어야 하고, EMR에서 처리되는 일괄처리 프로세스가 종료되기 전까지 Lambda 함수는 실행되지 않고 캡처된 데이터가 스트림에 유지되어야 합니다. 다음 순서와 같이 진행됩니다.:

  1. Amazon Kinesis Stream에 대해 데이터 실시간 처리를 시작합니다.
  2. 실시간 처리 프로세스가 시작되자마자, 일괄 처리 프로세스를 시작합니다.
  3. 일괄 처리 프로세스가 완료되면 Amazon Kinesis Stream으로 부터 데이터를 추출하여 DynamoDB에 put_item 함수를 실행하는 Lambda 함수를 호출합니다.
  4. 애플리케이션의 엔드포인트를 MySQL에서 DynamoDB를 바라보도록 설정을 변경합니다.

단계 1:  변경데이터캡처및 Amazon Kinesis Streams에밀어넣기

먼저, MySQL으로부터 트렌젝션 데이터를 캡처할 Amazon Kinesis Stream을 생성합니다. Data retention period 값을 일괄 처리 프로세스의 예상 처리시간에 맞춰 설정합니다. 데이터 무결성을 위해서는 데이터 보관 기간을 일괄 처리 프로세스가 실행되는 기간 동안 발생하는 모든 트랜잭션을 보관하기 충분할 정도로 길게 설정해야 하지만, 보관 기간을 반드시 최대값으로 설정할 필요는 없습니다. 마이그레이션 대상 데이터의 양에 따라 설정합니다.

MySQL 설정에서, BinLogStreamReader 모듈이 트랜잭션 데이터를 캡처할수 있도록 binlog_format 설정값을 ROW로 설정합니다. Binlog를 활성화하려면 log_bin 매개변수도 설정되어야 합니다. 더 상세한 내용은 AWS 데이터베이스 블로그의 Streaming Changes in a Database with Amazon Kinesis 포스트를 참조하시기 바랍니다.

[mysqld]
secure-file-priv = ""
log_bin=/data/binlog/binlog
binlog_format=ROW
server-id = 1
tmpdir=/data/tmp

다음 예제 코드는 트랜잭션 데이터를 캡처하여 Amazon Kinesis Stream으로 밀어넣는 Python 예제 코드입니다.

#!/usr/bin/env python
from pymysqlreplication import BinLogStreamReader
from pymysqlreplication.row_event import (
  DeleteRowsEvent,
  UpdateRowsEvent,
  WriteRowsEvent,
)

def main():
  kinesis = boto3.client("kinesis")

  stream = BinLogStreamReader(
    connection_settings= {
      "host": "<host IP address>",
      "port": <port number>,
      "user": "<user name>",
      "passwd": "<password>"},
    server_id=100,
    blocking=True,
    resume_stream=True,
    only_events=[DeleteRowsEvent, WriteRowsEvent, UpdateRowsEvent])

  for binlogevent in stream:
    for row in binlogevent.rows:
      event = {"schema": binlogevent.schema,
      "table": binlogevent.table,
      "type": type(binlogevent).__name__,
      "row": row
      }

      kinesis.put_record(StreamName="<Amazon Kinesis stream name>", Data=json.dumps(event), PartitionKey="default")
      print json.dumps(event)

if __name__ == "__main__":
main()

다음 코드는 위 Python 스크립트에 의해 생성된 JSON 데이터 예제입니다. 각 트랜잭션은 JSON 데이터에 다음과 같은 type 속성으로 기록됩니다:

  • WriteRowsEvent = INSERT
  • UpdateRowsEvent = UPDATE
  • DeleteRowsEvent = DELETE
{"table": "purchase_temp", "row": {"values": {"orderid": "orderidA1", "quantity": 100, "customerid": "customeridA74187", "productid": "productid1"}}, "type": "WriteRowsEvent", "schema": "test"}
{"table": "purchase_temp", "row": {"before_values": {"orderid": "orderid1", "quantity": 1, "customerid": "customerid74187", "productid": "productid1"}, "after_values": {"orderid": "orderid1", "quantity": 99, "customerid": "customerid74187", "productid": "productid1"}}, "type": "UpdateRowsEvent", "schema": "test"}
{"table": "purchase_temp", "row": {"values": {"orderid": "orderid100", "quantity": 1, "customerid": "customerid74187", "productid": "productid1"}}, "type": "DeleteRowsEvent", "schema": "test"}

단계 2. MySQL에서 DynamoDB로 데이터 덤프하기

DMS를 사용하는 가장 손쉬운 방법 중 하나는, 최근 추가된 Amazon S3를 마이그레이션 대상으로 사용하는 것입니다. S3를 대상으로 할 경우, full load 및 CDC 데이터가 CSV 형식으로 저장됩니다. 그러나, CDC의 경우에는 UPDATE 및 DELETE 문의 지원되지 않아 마이그레이션에 적합하지 않습니다. 보다 상세한 내용은 AWS Database Migration Service에서 Amazon S3를 대상으로 사용 문서를 참조하십시오.

Amazon S3로 데이터를 업로드하는 다른 방법은 스크립트에서 INTO OUTFILE SQL 절과 aws s3 sync CLI 명령어를 병렬로 사용하는 것입니다. 병렬 처리 수준은 서버 용량 및 로컬 네트워크 대역폭에 따라 달라집니다. pt-archiverPercona Toolkit 에 포함된 도구입니다. 상세 내용은 appendix를 참조하십시오. )와 같은 3rd party 도구도 유용하게 사용할 수 있습니다.

SELECT * FROM purchase WHERE <condition_1>
INTO OUTFILE '/data/export/purchase/1.csv' FIELDS TERMINATED BY ',' ESCAPED BY '\\' LINES TERMINATED BY '\n';
SELECT * FROM purchase WHERE <condition_2>
INTO OUTFILE '/data/export/purchase/2.csv' FIELDS TERMINATED BY ',' ESCAPED BY '\\' LINES TERMINATED BY '\n';
...
SELECT * FROM purchase WHERE <condition_n>
INTO OUTFILE '/data/export/purchase/n.csv' FIELDS TERMINATED BY ',' ESCAPED BY '\\' LINES TERMINATED BY '\n';

여기에서 다루는 사용사례의 경우 aws s3 sync 명령어를 추천합니다. 이 명령어는 내부적으로 S3 multipart 업로드기능을 사용하여 동작하고 패턴 매칭을 통해 특정파일을 포함하거나 제외시킬 수 있습니다. 또한, sync 명령어는 로컬 버전과 S3 버전 간에 파일 크기와 수정시간을 비교하여 서로 다른 경우에만 동기화를 수행하기 때문에 동기화 프로세스가 처리 도중에 중단되더라도 동일한 파일을 다시 업로드할 필요가 없습니다. 더 상세한 내용은 AWS CLI 명령어 참조문서의 sync command를 참고하시기 바랍니다.

$ aws s3 sync /data/export/purchase/ s3://<your bucket name>/purchase/ 
$ aws s3 sync /data/export/<other path_1>/ s3://<your bucket name>/<other path_1>/
...
$ aws s3 sync /data/export/<other path_n>/ s3://<your bucket name>/<other path_n>/ 

모든 데이터가 S3로 업로드된 후, 데이터를 DynamoDB에 밀어넣기 위해서는 다음과 같은 두가지 방법이 있습니다.:

  • 외부 테이블을 이용하여 Hive사용
  • MapReduce 코드 작성

외부 테이블을 이용하여 Hive 사용

S3의 데이터에 대해서 Hive 외부테이블을 생성하고 org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler 속성을 사용하여 생성한 DynamoDB 테이블을 대상으로 하는 다른 외부 테이블에 S3와 연결된 외부 테이블의 내용을 밀어넣습니다. 더 나은 생산성과 확장성을 위해 Hive용 UDF 모음인 Brickhouse를 사용하는 것을 고려해 볼 수 있습니다.

다음 샘플 코드는 DynamoDB용 Hive 테이블이 ARRAY<STRING> 타입의 products 컬럼으로 생성되었다고 가정합니다. Productidquantity 컬럼은 customeridorderid별로 그룹화되어 Brickhouse에서 제공하는 CollectUDAF 컬럼을 사용하여 products 컬럼에 삽입됩니다.

hive> DROP TABLE purchase_ext_s3; 
--- To read data from S3 
hive> CREATE EXTERNAL TABLE purchase_ext_s3 (
customerid string,
orderid    string,
productid  string,
quantity   string) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
LOCATION 's3://<your bucket name>/purchase/';

Hive> drop table purchase_ext_dynamodb ; 
--- To connect to DynamoDB table  
Hive> CREATE EXTERNAL TABLE purchase_ext_dynamodb (
      customerid STRING, orderid STRING, products ARRAY<STRING>)
      STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' 
      TBLPROPERTIES ("dynamodb.table.name" = "purchase", 
      "dynamodb.column.mapping" = "customerid:customerid,orderid:orderid,products:products");

--- Batch-puts to DynamoDB using Brickhouse 
hive> add jar /<jar file path>/brickhouse-0.7.1-SNAPSHOT.jar ; 
hive> create temporary function collect as 'brickhouse.udf.collect.CollectUDAF';
hive> INSERT INTO purchase_ext_dynamodb 
select customerid as customerid , orderid as orderid
       ,collect(concat(productid,':' ,quantity)) as products
      from purchase_ext_s3
      group by customerid, orderid; 

불행히도 DynamoDBStorageHandler클래스는 MAP, LIST, BOOLEAN 및 NULL  데이터형을 지원하지 않기 때문에 ARRAY<STRING> 데이터형을 선택하였습니다. Hive의 ARRAY<STRING> 형식의 products 컬럼은 DynamoDB의 StringSet데이터형 속성으로 변환됩니다. 샘플코드는 Brickhouse가 어떤 식으로 동작하는지, 어떻게 원하는 복수의 레코드들을 골라 DynamoDB의 하나의 StringSet  데이터형 속성으로 병합할 수 있는지 보여줍니다.

Hadoop Streaming으로 Python MarReduce 코드 작성하기
맵퍼 작업은 S3의 입력데이터로부터 각 레코드를 읽고 입력 키-값 쌍을 중간 키-값 쌍으로 매핑합니다. S3의 원본 데이터를 탭 문자(“\t)로 구분된 키 부분과 값 부분의 두 부분으로 나눕니다. 맵퍼 데이터는 중간 키(customeridorderid) 값으로 정렬되어 reducer로 전송됩니다. reducer단계에서 각 레코드들이 DynamoDB에 저장합니다.

#!/usr/bin/env python
import sys
 
# get all lines from stdin
for line in sys.stdin:
    line = line.strip()
    cols = line.split(',')
# divide source data into Key and attribute part.
# example output : “cusotmer1,order1	product1,10”
    print '%s,%s\t%s,%s' % (cols[0],cols[1],cols[2],cols[3] )

일반적으로 reduce 작업은 매핑( 키 / 값 목록의 쌍 ) 프로세스가 생성한 결과값을 수신한 뒤 각 키에 대해 값의 목록에 대한 작업을 수행합니다.

여기서는 reducer를 STDIN/STDOUT/Hadoop streaming을 기반으로 하여 Python으로 작성하였습니다. 문제는 이와 같은 경우 열거형 데이터 형식을 사용할 수 없다는 것입니다. 이와 같은 경우 reducer를 매퍼의 중간 키값 – 이 경우, customeridoerderid(cols[0],cols[1]) -으로 정렬된 데이터를 수신하고 모든 속성을 item_data dictionary의 특정 키로 저장합니다. Item_data dictionary의 속성들은 sys.stdin에서 새 중간 키가 들어올 대마다 DynamoDB에 입력되거나 플러싱됩니다.

#!/usr/bin/env python
import sys
import boto.dynamodb
 
# create connection to DynamoDB
current_keys = None
conn = boto.dynamodb.connect_to_region( '<region>', aws_access_key_id='<access key id>', aws_secret_access_key='<secret access key>')
table = conn.get_table('<dynamodb table name>')
item_data = {}

# input comes from STDIN emitted by Mapper
for line in sys.stdin:
    line = line.strip()
    dickeys, items  = line.split('\t')
    products = items.split(',')
    if current_keys == dickeys:
       item_data[products[0]]=products[1]  
    else:
        if current_keys:
          try:
              mykeys = current_keys.split(',') 
              item = table.new_item(hash_key=mykeys[0],range_key=mykeys[1], attrs=item_data )
              item.put() 
          except Exception ,e:
              print 'Exception occurred! :', e.message,'==> Data:' , mykeys
        item_data = {}
        item_data[products[0]]=products[1]
        current_keys = dickeys

# put last data
if current_keys == dickeys:
   print 'Last one:' , current_keys #, item_data
   try:
       mykeys = dickeys.split(',')
       item = table.new_item(hash_key=mykeys[0] , range_key=mykeys[1], attrs=item_data )
       item.put()
   except Exception ,e:
print 'Exception occurred! :', e.message, '==> Data:' , mykeys

MapReduce 작업을 실행하려면 EMR 마스터 노드에 접속하여 Hadoop 스트리밍 작업을 실행하십시오. hadoop-streaming.jar 파일 위치 및 파일 이름은 EMR 버전에 따라 다를 수 있습니다. reducer가 실행되는 동안 발생하는 exception 메시지들은 -output 옵션으로 지정한 디렉토리에 저장됩니다. 예외 또는 오류의 원인이되는 데이터를 식별하기 위해 해시 키 및 범위 키 값들도 기록됩니다.

$ hadoop fs -rm -r s3://<bucket name>/<output path>
$ hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar \
           -input s3://<bucket name>/<input path> -output s3://<bucket name>/<output path>\
           -file /<local path>/mapper.py -mapper /<local path>/mapper.py \
           -file /<local path>/reducer.py -reducer /<local path>/reducer.py

위 스크립트와 자체 생성한 테스트 데이터를 사용하여 수행한 마이그레이션 테스트에서 데이터베이스 크기 및 데이터 마이그레이션을 완료하기까지 걸린 시간은 다음과 같습니다.

Server MySQL instance m4.2xlarge
EMR cluster master : 1 x m3.xlarge

core  : 2 x m4.4xlarge

DynamoDB 2000 write capacity unit
Data Number of records 1,000,000,000
Database file size (.ibc) 100.6 GB
CSV files size 37 GB
Performance (time) Export to CSV 6 min 10 sec
Upload to S3 (sync) 3 min 30 sec
Import to DynamoDB depending on write capacity unit

다음 스크린샷은 마이그레이션 작업 도중 write capacity 사용 결과를 보여줍니다.

성능 결과는 사용한 서버 용량과 네트워크 대역폭, 병렬 처리 수준, 변환 로직, 사용 프로그램 언어 및 기타 조건에 달라질 수 있습니다. 이 경우 프로비저닝된 write capacity unit이 모두 데이터 import를 위해 사용한 MapReduce 작업에 의해 소비되었으므로, EMR 클러스터의 크기 및 DynamoDB 테이블의 write capacity unit을 늘릴 수록 데이터 이전작업 완료에 걸리는 시간을 단축할 수 있습니다. Jave 기반 MapReduce 코드를 사용할 경우 MapReduce 프레임워크 사용 및 함수 작성시 보다 많은 유연성을 제공합니다.

단계 3: Amazon Lambda 함수를 사용하여 Amazon Kinesis로부터 데이터를 읽고 DynamoDB에 업데이트하기

AWS Lambda 콘솔에서 Create a Lambda functionkinesis-process-record-python blueprint를 선택합니다. 다음 버튼을 클릭하고 Configure triggers 페이지에서 생성한 Kinesis stream을 선택합니다.

생성한 Lambda 함수가 Amazon Kinesis 스트림을 읽고 데이터를 DynamoDB에 쓸 수 있도록 해당 권한을 가진 IAM role을 설정하여야 합니다.

Lambda 함수는 각 레코드의 type 속성을 확인하여 트랜잭션 유형을 식별합니다. 트랜잭션 유형에 따라 변환 및 업데이트 방법이 결정됩니다.

예를 들어 JSON 레코드가 함수에 전달되면 함수는 type 속성을 확인하고 DynamoDB 테이블에 들어온 레코드와 동일한 키를 가진 아이템이 이미 존재하는지 확인합니다. 만약 동일한 키를 가진 아이템이 이미 있다면 기존 아이템을 조회하여 dictionary 변수 (다음 코드에서는 item 변수)에 저장하고 DynamoDB 테이블에 저장하기 전에 dictionary 변수에 저장된 기존 아이템 정보에 새로 전달된 정보를 반영하여 저장합니다. 이렇게 해서 들어오는 레코드가 기존 항목을 덮어 쓰지 않도록 합니다.

from __future__ import print_function

import base64
import json
import boto3

print('Loading function')
client = boto3.client('dynamodb')

def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))
    for record in event['Records']:
        # Amazon Kinesis data is base64-encoded so decode here
        payload = base64.b64decode(record['kinesis']['data'])
        print("Decoded payload: " + payload)
        data = json.loads(payload)
        
        # user logic for data triggered by WriteRowsEvent
        if data["type"] == "WriteRowsEvent":
            my_table = data["table"]
            my_hashkey = data["row"]["values"]["customerid"]
            my_rangekey = data["row"]["values"]["orderid"]
            my_productid = data["row"]["values"]["productid"]
            my_quantity = str( data["row"]["values"]["quantity"] )
            try:
                response = client.get_item( Key={'customerid':{'S':my_hashkey} , 'orderid':{'S':my_rangekey}} ,TableName = my_table )
                if 'Item' in response:
                    item = response['Item']
                    item[data["row"]["values"]["productid"]] = {"S":my_quantity}
                    result1 = client.put_item(Item = item , TableName = my_table )
                else:
                    item = { 'customerid':{'S':my_hashkey} , 'orderid':{'S':my_rangekey} , my_productid :{"S":my_quantity}  }
                    result2 = client.put_item( Item = item , TableName = my_table )
            except Exception, e:
                print( 'WriteRowsEvent Exception ! :', e.message  , '==> Data:' ,data["row"]["values"]["customerid"]  , data["row"]["values"]["orderid"] )
        
        # user logic for data triggered by UpdateRowsEvent
        if data["type"] == "UpdateRowsEvent":
            my_table = data["table"]
            
        # user logic for data triggered by DeleteRowsEvent    
        if data["type"] == "DeleteRowsEvent":
            my_table = data["table"]
            
            
    return 'Successfully processed {} records.'.format(len(event['Records']))

단계 4:  애플리케이션 엔드포인트를 MySQL에서 DynamoDB로 변경하기

애플리케이션이 MySQL 대신 DynamoDB를 데이터베이스로 사용하려면 애플리케이션 코드를 리팩토링해야 합니다. 애플리케이션의 데이터베이스 액세스에 대한 모든 경우를 여기에서 다루기는 어렵기 때문에, 여기서는 다음의 간단한 자바 코드로 데이터베이스 연결 및 쿼리 부분이 어떻게 바뀌어야 하는지 확인해 보겠습니다. 더 자세한 내용에 대해서는 DynamoDB 및 AWS SDK를 사용한 프로그래밍 문서를 참조하시기 바랍니다.

MySQL 쿼리 코드 예제

다음 샘플 코드는 MySQL 데이터베이스에 연결하고 데이터를 조회하는 일반적인 방법을 보여줍니다.

import java.sql.* ;
...
try {
    Connection conn =  DriverManager.getConnection("jdbc:mysql://<host name>/<database name>" , "<user>" , "<password>");
    stmt = conn.createStatement();
    String sql = "SELECT quantity as quantity FROM purchase WHERE customerid = '<customerid>' and orderid = '<orderid>' and productid = '<productid>'";
    ResultSet rs = stmt.executeQuery(sql);

    while(rs.next()){ 
       int quantity  = rs.getString("quantity");   //Retrieve by column name 
       System.out.print("quantity: " + quantity);  //Display values 
       }
} catch (SQLException ex) {
    // handle any errors
    System.out.println("SQLException: " + ex.getMessage());}
...
==== Output ====
quantity:1

DynamoDB 쿼리 코드 예제

DynamoDB에서 데이터를 조회하려면 다음 단계를 따르면 됩니다:

  1. AmazonDynamoDBClient 및 ProfileCredentialProvider를 이용하여 DynamoDB 클래스의 인스턴스 생성
  2. DynamoDB 클래스 인스턴스의 getTable method를 사용하여 대상 Table 클래스 인스턴스 획득
  3. withHashKey및 withRangeKeyCondition method를 사용하여 QuerySpec 클래스 인스턴스 생성
  4. QuerySpec 클래스 인스턴스를 사용하여 Table 클래스 인스턴스의 query method를 실행. 결과값이 JSON 형식으로 반환되므로, 결과값에 대하여 특정 속성 값을 확인하기 위하여 getJSON method 사용
...
DynamoDB dynamoDB = new DynamoDB( new AmazonDynamoDBClient(new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("purchase");

QuerySpec querySpec = new QuerySpec()
        .withHashKey("customerid" , "customer1")  // hashkey name and its value 
        .withRangeKeyCondition(new RangeKeyCondition("orderid").eq("order1") ) ; // Ranage key and its condition value 

ItemCollection<QueryOutcome> items = table.query(querySpec); 

Iterator<Item> iterator = items.iterator();          
while (iterator.hasNext()) {
Item item = iterator.next();
System.out.println(("quantity: " + item.getJSON("product1"));   // 
}
...
==== Output ====
quantity:1

맺음말
이 글에서는 MySQL에서 DynamoDB로 데이터를 원활하게 마이그레이션하고 마이그레이션 중 중단 시간을 최소화하기 위한 두 가지 방안을 소개했습니다. 방안 #1에서는 DMS를 사용하였고, 방안 #2에서는 EMR, Amazon Kinesis 및 Lambda를 복합적으로 사용하였습니다. 또한 각 데이터베이스의 특성에 따라 키 디자인을 변환하여 읽기 및 쓰기 성능을 개선하고 비용을 절감하는 방법도 설명했습니다. 각 방안은 서로 장단점이 있으므로 비즈니스 요구 사항에 따라 어떤 접근방법을 취할지 고려할 필요가 있습니다.

여기에서 사용한 예제 코드들은 다양한 환경에서 완벽하고 효율적이며 신뢰할 수 있는 데이터 마이그레이션 용으로 재사용되기에 충분한 수준이 아닙니다. 데이터 마이그레이션을 시작하기 전에 참조용으로 사용하시고 실제 마이그레이션에서는 신뢰할 수 있는 마이그레이션을 수행할 수 있도록 모든 요소들을 충분히 고려하여 작성되어야 합니다.

이 글이 여러분의 데이터베이스 마이그레이션을 계획 및 구현하고 서비스 중단을 최소화하는데 도움이 되기를 바랍니다.

Appendix

Percona Toolkit 설치법:

# Install Percona Toolkit
$ wget https://www.percona.com/downloads/percona-toolkit/3.0.2/binary/redhat/6/x86_64/percona-toolkit-3.0.2-1.el6.x86_64.rpm
$ yum install perl-IO-Socket-SSL
$ yum install perl-TermReadKey
$ rpm -Uvh percona-toolkit-3.0.2-1.el6.x86_64.rpm

Pt-archiver 실행 예제:

# run pt-archiver
$ pt-archiver –source h=localhost,D=blog,t=purchase –file ‘/data/export/%Y-%m-%d-%D.%t’  –where “1=1” –limit 10000 –commit-each

이 글은 AWS 빅데이터 서비스의 기술 지원 엔지니어인 이용성님이 작성하신 글 Near Zero Downtime Migration from MySQL to DynamoDB을 AWS 솔루션즈 아키텍트인 김병수님이 번역해 주셨습니다.

DynamoDB Accelerator (DAX) 정식 출시

올해 초에 Amazon DynamoDB Accelerator (DAX) – 읽기 작업을 위한 인-메모리 캐싱 기능를 공개하였습니다. DAX는 캐싱된 응답을 마이크로 초 단위로 반환하므로, 일관성 있는 읽기 집약적인 작업 부하에 적합합니다. DAX는 DynamoDB API를 지원하며 완전 관리 서비스로서 DAX 클러스터를 만들고 이를 기존 읽기 및 쓰기의 대상으로 지정하면 됩니다. 패치, 클러스터 유지 관리, 복제 또는 결함 관리에 대해 걱정할 필요가 없습니다. DAX 정식 출시
오늘 DAX가 정식 출시되었으며, 미국 동부 (버지니아 북부), EU (아일랜드), 미국 서부 (오레곤), 아시아 태평양 (도쿄) 및 미국 서부 (캘리포니아 북부) 등 현재 5 개 리전에서 DAX를 사용할 수 있습니다. 기존 미리 보기 베타 고객은 정식 서비스 환경에서 DAX를 사용 중이며, DAX를 애플리케이션에 추가하는 것이 매우 쉽고 기존 애플리케이션이 10 배 빠르게 실행되고 있다는 피드백을 보내주셨습니다.

이전 게시물에서 간략히 설명한 것처럼 DAX를 사용하여 기존 DynamoDB 속도를 높이기 위해 원하는 리전에 DAX 클러스터를 만들고 응용 프로그램을 업데이트하여 DAX SDK for Java를 참조하고 SDK를 구성하여 클러스터 엔드 포인트를 사용하도록 구성합니다.  앞으로 다른 언어에 대한 SDK 지원을 위해 노력하고 있으며 추가 정보가 있을 때 공유 할 것입니다.

DAX 가격 구조
미국 동부 (버지니아 북부) 및 미국 서부 (오레곤) 지역의 시간당 $ 0.269에서 시작하는 시간 당 클러스터의 각 노드 (자세한 내용은 DynamoDB 요금 페이지 참조)에 대해 지불합니다. DAX를 사용하면 클러스터의 각 노드가 고 가용성을 위한 읽기 대상 및 장애 조치 대상의 역할을 합니다. DAX SDK는 클러스터를 인식하며 클러스터의 모든 노드에 대해 번갈아 요청을 실행하므로 클러스터의 캐시 리소스를 최대한 활용할 수 있습니다.

Jeff;

이 글은 DynamoDB Accelerator (DAX) Now Generally Available의 한국어 번역입니다.

Amazon DynomoDB 자동 스케일링 기능 출시!

Amazon DynamoDB는 다양한 산업 및 사례에 걸쳐 십만이 넘는 고객을 보유하고 있습니다. 스타트업 부터 엔터프라이즈까지 다양한 규모의 고객은 전 세계 16 개 리전에서 DynamoDB의 일관된 성능을 활용합니다. 최근 경향은 DynamoDB를 사용하여 서버리스(Serverless) 애플리케이션 백엔드 저장소로 활용하는 고객이 늘고 있다는 것입니다. DynamoDB를 사용하면 서버 프로비저닝, OS 및 데이터베이스 소프트웨어 패치 수행, 고 가용성을 보장하기 위한 가용 영역 복제 구성 등의 작업이  필요 없습니다. 간단히 테이블을 만들고 데이터를 추가하기 만하면 됩니다.

DynamoDB는 응용 프로그램에 필요한 읽기 및 쓰기 용량을 설정할 수 있는 프로비저닝 용량 모델을 제공합니다. 이로 인해, 용량 걱정 없이 간단한 API 호출 또는 AWS 관리 콘솔에서 버튼 클릭으로 테이블에 대한 용량을 변경할 수 있습니다.

이에 더 나아가 오늘 DynamoDB에 자동 스케일링(Auto Scaling)을 도입하여 테이블 및 글로벌 보조 인덱스 용량 관리를 자동화 기능을 출시합니다. 이는 원하는 대상 활용 방법에 대해  읽기 및 쓰기 용량의 상한 및 하한선을 설정하면 됩니다. 그런 다음 DynamoDB는 Amazon CloudWatch 알림을 사용하여 처리량 소비를 모니터링 한 다음 필요할 때 프로비저닝 된 용량을 조정합니다. Auto Scaling은 모든 새로운 테이블과 인덱스에 대해 기본적으로 설정 되며, 기존 테이블과 인덱스에도 구성 할 수 있습니다.

DynamoDB Auto Scaling은 테이블 및 인덱스를 모니터링하여 응용 프로그램 트래픽의 변화에 ​​따라 처리량을 자동 조정합니다. 이를 통해 DynamoDB 데이터를 보다 쉽게 ​​관리하고 응용 프로그램의 가용성을 극대화하며 DynamoDB 비용을 줄일 수 있습니다.

함께 살펴 보겠습니다.

자동 스케일링 기능 설정 방법
이제 DynamoDB 콘솔에서 새 테이블을 만들 때, 기본 매개 변수(Parameter) 집합을 제안합니다. 기본 설정을 그대로 사용하거나 기본 설정 사용을 선택 취소하고 자체 매개 변수를 입력 할 수 있습니다.

자신의 매개 변수를 입력하는 방법은 다음과 같습니다.

목표 사용률은 소비 용량 대 공급 용량의 비율로 표시됩니다. 위의 매개 변수를 사용하면 읽기 또는 쓰기 요청이 급작스럽게 늘어 소비 된 용량을 두 배로 늘릴 수 있는 충분한 여유 공간 (DynamoDB 읽기 및 쓰기 작업과 제공된 용량 간의 관계에 대해 자세한 사항은 용량 단위 계산 참고)이 허용됩니다. 프로비저닝 용량 변경은 백그라운드로 처리됩니다.

자동 스케일링 기능 사용해 보기
새 기능을 실제로 사용하려면 설명서 지침을 참고하세요. 나는 새로운 EC2 인스턴스를 시작하고 (sudo pip install boto3) AWS SDK for Python을 구성 (aws configure)을 합니다. 그런 다음 Python 및 DynamoDB 소스 코드를 사용하여 일부 데이터로 테이블을 만들고, 읽기 및 쓰기 용량을 각각 5 로 수동구성했습니다.

CloudWatch 측정 항목에 대한 자동 스케일링 조정의 효과를 보여줄 수 있습니다. 다음은 적용하기 전에 측정 항목 통계입니다.

3 단계에서 코드를 수정하여 1920 년에서 2007 년 사이의 임의의 연도에 대한 쿼리를 지속적으로 발행하고 코드의 단일 복사본을 실행 한 다음 1 ~ 2 분 후에 읽기 통계를 확인했습니다.

소비 용량은 제공된 용량보다 높으므로, 읽기 트래픽 제한이 발생합니다. 자동 스케일링을을 한번 적용해 봅시다. 콘솔로 돌아와 내 테이블의 Capacity 탭을 클릭했습니다. 그런 다음 Read capacity을 클릭하고 기본값을 그대로 사용하고 Save을 클릭했습니다.

DynamoDB 읽기 용량의 자동 확장을 관리하기 위해, 새로운 IAM 역할 (DynamoDBAutoscaleRole)과 한 쌍의 CloudWatch 알람을 생성했습니다.

DynamoDB 자동 스케일링은 알람 임계 값을 관리하여, 스케일링 프로세스가 진행됩니다. 첫 번째 알림이 시작되어, 추가 읽기 용량이 프로비저닝 된 동안 테이블 상태가 업데이트로 변경되었습니다.

변경 사항은 몇 분 내에 읽기 측정 항목에서 볼 수 있습니다.

수정 된 쿼리 스크립트의 몇 가지 추가 복사본을 시작하고 추가 용량이 프로비저닝 된 것을 확인했습니다 (빨간색 선으로 표시).

모든 스크립트를 끄고, 스케일 다운 알람이 울리기를 기다리는 후 얻은 결과 입니다.

다음날 아침 Scaling activities을 점검하여, 알람이 밤새 여러 번 트리거되었음을 확인했습니다.

이는 측정 항목에도 표시되었습니다.

지금까지 예상 용량에 맞게 읽기 용량을 설정하고, 초과 용량 (파란색 선과 빨간색 선 사이의 공간)을 돈을 지불함으로써 이러한 상황을 대비할 수 있습니다. 또한, 트래픽을 줄이면 너무 낮게 설정하고 모니터링하는 것을 잊어 버리고 트래픽이 소진 될 때 용량이 소진 될 수 있었습니다. 그러나, 자동 스케일링을 사용하면 수요가 증가하면, 더 많은 용량이 필요하다는 것을 나타내는 자동 응답과 용량이 더 이상 필요하지 않을 때 또 다른 자동 응답을 얻을 수 있습니다.

알아 두어야 할 점
DynamoDB Auto Scaling은 다소 예측 가능하고 일반적으로 주기적인 방식으로 변화하는 요청 속도를 수용하도록 설계되었습니다. 예기치 못한 읽기 작업의 급격한 변화를 수용 해야하는 경우, Amazon DynamoDB Accelerator (DAX) – 읽기 작업을 위한 인-메모리 캐싱 기능)와 자동 스케일링 기능을 함께 사용해야 합니다. 또한 AWS SDK는 급격한 요청에 제한된 읽기 및 쓰기 요청을 감지하고 적절한 지연이 있은 후, 다시 시도합니다.

앞서 언급한 DynamoDBAutoscaleRole는 테이블 및 인덱스를 확장 할 수 있도록 자동 스크롤링에 필요한 권한을 제공합니다. 이 역할과 이 역할이 사용하는 권한에 대한 자세한 내용을 보려면 DynamoDB 자동 스케일링에 대한 사용자 권한 부여를 참고하시기 바랍니다.

자동 스케일링 정책 활성화 및 비활성화하는 기능을 포함하여 AWS CLI 및 API를 완벽하게 지원합니다. 예측 가능한 시간 제한이 있는 트래픽이 발생하는 경우, 프로그래밍 방식으로 자동 스케일링 정책을 비활성화하고 설정된 시간 동안 더 높은 처리량을 제공 한 다음 나중에 자동 확장을 다시 활성화 할 수도 있습니다.

DynamoDB의 제한 페이지에서 언급했듯이 필요한 만큼 자주 필요한 용량만큼 (요청에 따라 늘릴 수 있는 계정 당 한도에 따라) 프로비저닝 된 용량을 늘릴 수 있습니다  각 테이블 또는 글로벌 보조 인덱스에 대해 용량을 하루에 최대 9 회까지 줄일 수 있습니다.

정기적으로 DynamoDB 요금에 따라 제공하는 용량에 대해 비용을 지불합니다. 추가 절감을 위해 DynamoDB 예약 용량을 구입할 수도 있습니다.

정식 출시
이 기능은 현재 서울 리전을 포함한 모든 지역에서 지금 사용할 수 있습니다!

Jeff;

이 글은 New – Auto Scaling for Amazon DynamoDB의 한국어 번역입니다.

Amazon DynamoDB Accelerator (DAX) – 읽기 작업을 위한 인-메모리 캐싱 기능

여러분은 이미 Amazon DynamoDB에 대해 잘 알고 계실 겁니다. 필요한 만큼만 사용하는 테이블 공간, 읽기 및 쓰기 용량을 자유롭게 변경가능한 확장성 높은 관리 NoSQL 데이터베이스입니다. 응답 시간은 수 밀리 초 단위로서 광고 기술, IoT, 게임, 미디어, 온라인 학습, 여행, 전자 상거래 및 금융 영역의 다양한 고객들이 여러 유형의 애플리케이션에서 사용하고 있습니다. 고객 중 일부는 단일 DynamoDB 테이블에 100 테라 바이트 이상을 저장하고 초당 수백만 건의 읽기 또는 쓰기 요청을 처리합니다. Amazon 소매 사이트는 DynamoDB를 사용하여 Black Friday, Cyber ​​Monday 및 Prime Day와 같은 높은 트래픽을 처리하고 있습니다.

DynamoDB의 애플리케이션 및 작업 부하 성능 향상을 위해 일부 작업(게임 및 광고 서비스 등에서)에 대해 최대한 빨리 DynamoDB에서 데이터를 가져 오는 기능을 사용하면 클릭률 높은 게임 또는 광고를 더 빠르게 처리할 수 있습니다.

Amazon DynamoDB Accelerator 신규 출시
이러한 고객의 워크로드를 지원하기위해 Amazon DynamoDB Accelerator (DAX) 공개 미리보기를 시작합니다.

DAX는 DynamoDB 테이블 앞에 논리적으로 배치되는 완전 관리 캐싱 서비스입니다. 쓰기 모드(Write-Through)에서 작동하며 DynamoDB와 API 호환됩니다. 각 응답은 마이크로 초 단위로 캐시에서 반환되므로 DAX는 일관성 있는 읽기 집약적 작업 부하에 매우 적합합니다. DAX는 관리 서비스로서 유연하고 쉽게 사용할 수 있어, DAX 클러스터를 만들고 이를 기존 읽기 및 쓰기 방식으로 사용하면됩니다. 패치, 클러스터 유지 관리, 복제 또는 결함 관리에 대해 걱정할 필요가 없습니다.

각 DAX 클러스터에는 1-10개의 노드가 포함될 수 있습니다. 전체 읽기 처리량을 높이기 위해 노드를 추가 할 수 있습니다. 캐시 크기(작업 집합이라고도 함)는 클러스터를 만들 때 선택하는 노드 크기 (dax.r3.large에서 dax.r3.8xlarge)를 기반으로합니다. 클러스터는 노드가 가용 영역(AZ)에 걸쳐있는 VPC 내에서 실행됩니다.

DAX와 통신하려면 Java용 DAX SDK를 사용해야합니다. 이 SDK는 낮은 대기 시간과 높은 처리를 위한 저수준의 TCP 인터페이스를 사용하여 클러스터와 통신합니다 (가능한 한 빨리 다른 언어를 통한 DAX 접근 지원할 예정).

DAX 클러스터 만들기
DynamoDB Console에서 DAX 클러스터를 만듭니다 (API 및 CLI 지원도 가능). 콘솔을 열고 Create cluster를 클릭하여 시작하십시오.

이름과 설명을 입력하고, 노드 유형을 선택하고, 클러스터 크기를 설정합니다. 그런 다음 DAX에서 DynamoDB 테이블에 접근할 수있는 권한을 부여하는 IAM 역할 및 정책을 만듭니다 (기존 역할을 선택할 수도 있음).

콘솔을 사용하면 단일 테이블에 대한 접근 권한을 부여하는 정책을 만들 수 있습니다. IAM Console을 사용하여 정책에 테이블을 추가합니다.

다음으로 DAX가 클러스터 노드를 배치하는 데 사용하는 서브넷 그룹을 만듭니다. 그룹의 이름을 지정하고 원하는 서브넷을 선택합니다.

기본 설정을 그대로 사용하고 Launch cluster을 클릭합니다.

클러스터는 몇 분 안에 사용할 준비가 되었습니다.

다음 단계는 애플리케이션을 업데이트하여 Java용 DAX SDK를 통해 클러스터 엔드포인트 (이 경우 dax1.seutl3.clustercfg.dax.use1.cache.amazonaws.com:8111)을 사용하도록 구성하는 것입니다.

애플리케이션이 실행되면, Metrics 탭을 방문하여 캐시 성능을 확인할 수 있습니다. Amazon CloudWatch 메트릭에는 캐시량 및 누락 횟수, 요청 횟수, 오류 카운트 등이 포함됩니다.

Alarms 탭을 사용하여 모든 측정 항목에 대한 CloudWatch 알람을 생성 할 수 있습니다. 캐시 누락이 발생하는지 알고 싶습니다.

Node 탭을 사용하여 클러스터의 노드를 볼 수 있습니다. 새 노드를 추가하거나 기존 노드를 삭제할 수도 있습니다.

AX의 작동 방식을 확인하기 위해 DAX Sample Application을 설치하고 두 번 실행했습니다. 첫 번째 실행은 DynamoDB에 직접 접근하여 캐시 되지 않은 기본 성능을 시연했습니다.

중간 결과 그룹에서 볼 수 있듯이 쿼리는 2.9에서 11.3 밀리 초 사이에 실행되었습니다. 두 번째 실행에서는 DAX를 사용하여 캐싱이 성능에 미치는 영향을 보여주었습니다.

각 테스트의 첫 번째 반복은 캐시 실패를 초래합니다. 후속 실행에서는 캐시에서 결과를 검색하고 (알 수 있듯이) 상당히 빠르게 수행합니다.

알아두면 좋을 사항
다음은 DAX를 사용자 환경에서 사용하는 방법을 생각할 때 염두에 두어야 할 몇 가지 사항입니다.

  • Java API – 앞서 언급했듯이 다른 언어에 대한 지원을 추가 할 계획으로 Java에 대한 지원으로 공개 미리보기를 시작합니다. DAX는 DynamoDB와 API 호환되므로 자체 캐싱 논리를 작성하거나 코드를 변경할 필요가 없습니다.
  • 일관성 – DAX는 최종 일관성 있는 읽기를 사용할 때 성능 향상을 위한 최상의 기회를 제공합니다.
  • 연속 쓰기(Write-throughs) – DAX는 연속 쓰기 캐시입니다. 다만, 읽기 내용과 작성한 내용 간에 약한 상관 관계가있는 경우 DynamoDB에 쓰기 작업을 할 수 있습니다. 이를 통해 DAX가 읽기에 더 큰 도움을 줄 수 있습니다.
  • 프로비저닝 해제 – 사용자 환경에서 DAX를 사용하면 기본 테이블에 대해 프로비저닝 된 읽기 용량을 줄일 수 있어야합니다. 이렇게 하면 DAX가 급격한 사용량 증가에 대비 한 여유 용량을 제공 할 수 있게 하면서 비용을 절감 할 수 있습니다.

정식 출시
미국 동부 (버지니아 북부), 미국 서부 (오레곤) 및 EU (아일랜드) 지역에서 DAX의 공개 미리 보기를 사용할 수 있으며 오늘 가입 하기할 수 있습니다. 공개 미리보기를 무료로 사용할 수 있으며 DAX Developer Guide를 통해 더 많은 정보를 얻을 수 있습니다.

Jeff;

이 글은 Amazon DynamoDB Accelerator (DAX) – In-Memory Caching for Read-Intensive Workloads의 한국어 번역입니다.

Amazon DynamoDB 시간 기반 (TTL) 데이터 관리 기능 출시

많은 AWS 고객들이 Amazon DynamoDB를 잘 활용하고 있습니다. 본 DB 서비스가 제공하는 속도와 유연성을 좋아하고, Ad Tech (참조 아키텍처), Gaming (참조 아키텍처), IoT (참조 아키텍처) 분야 등에서, 수 밀리 초 단위의 지연 시간을 원하는 다양한 애플리케이션 구축에 도움이 됩니다.  또한, DynamoDB가 수 테라 바이트 크기의 테이블에 대해 초당 수백만 건의 요청을 처리 할 수 ​​있는 완전 관리형 서버리스(Serverless) 데이터베이스라는 점도 매력적입니다.

DynamoDB 사용자는 데이터 수명이 낮거나 시간이 지남에 따라 접근 빈도가 낮은 데이터를 저장합니다. 대부분 최근 로그인 기록, 평가판 구독 또는 응용 프로그램 통계치를 추적합니다.  또한, 저장 기간에 대한 제약 또는 계약 상의 제한이 있는 데이터를 저장하기도 합니다. 지금까지 이러한 고객은 자체 시간 기반 데이터 관리 기능을 직접 구현했습니다. 대량으로 DynamoDB 항목을 검사한 뒤, 날짜 속성을 확인하며 더 이상 필요하지 않은 항목에 대한 삭제 요청을 실행해야 할 때는 Amazon Elastic Compute Cloud (EC2) 인스턴스를 실행해서 처리해야 했기 때문에, 애플리케이션 비용과 복잡성이 증가했습니다.

신규 시간 기반 (TTL) 데이터 관리 기능
이러한 요구 사항을 해결 하기 위해 오늘 시간 기반(Time to Live) 데이터 처리 기능을 새로 출시합니다. 데이터 아이템의 만료 시간을 항목 속성을 지정하여 테이블별로 본 기능을 활성화 할 수 있습니다.

항목 속성이 지정되고 TTL 관리가 활성화되면 (단일 API 호출이 두 작업 모두를 처리 함) DynamoDB는 만료 된 항목을 찾아 자동으로 삭제합니다. 본 처리 작업은 자동 및 백그라운드에서 수행되며 테이블에 대한 읽기 또는 쓰기 트래픽에는 영향을 주지 않습니다.

DynamoDB 스트림 (자세한 정보는 Sneak Preview – DynamoDB Streams 참조)을 사용하여, 삭제된 항목을 처리하거나 보관할 수 있습니다. 스트림 중 다른 업데이트 레코드처럼 삭제 작업은 24 시간 기준으로 가능합니다. AWS Lambda 및 DynamoDB Triggers를 사용하여 만료 된 항목을 장기 보관용 스토리지로 이동하거나, 다른 테이블을 업데이트 할 수 있습니다.

테이블에 TTL을 사용하고 원하는 속성을 지정하는 방법은 다음과 같습니다.

이 속성은 DynamoDB의 Number 데이터 유형에 있어야 하며 Unix Epoch 시간 시스템 당 초로 해석됩니다.

위 스크린 샷에서 볼 수 있듯이 DynamoDB 스트림을 활성화 할 수 있으며 TTL을 사용할 때 삭제 될 항목의 미리보기를 볼 수 있습니다.

또한, 프로그래밍 코드에서 UpdateTimeToLive 함수를 호출하거나 AWS 명령어 모드 (CLI)에서 update-time-to-liv 명령을 사용할 수 있습니다.

TUNE의 사용 사례
AWS 고객 인 TUNE은 이미 HasOffers 서비스 중에서 본 기능을  잘 활용하고 있습니다.

HasOffers-Dashboard-Phone

HasOffers는 고객이 마케팅 캠페인의 효과를 분석하고  대용량 광고 참여 데이터를  저장하는 기능을 제공합니다. 캠페인에 대한 고객이 정한 시간대가 지나면, 데이터가 더 이상 필요 없으며 삭제 될 수 있습니다. TUNE에서 TTL 기능을 사용하기 전에는 수동으로 이를 식별하여 과거 데이터를 삭제했습니다. 이는 직접 사람이 투여되어 컴퓨팅 리소스를 들여야 하는 일로 DynamoDB 테이블의 처리랑 일부를 사용했습니다.

이제는 각 항목의 만료 시간을 설정하고 나머지는 DynamoDB에 맡기면 됩니다. 불필요한 데이터는  처리량에 영향을 미치지 않으면서도, 자동으로 사라집니다. 결과적으로 TUNE은 85 테라 바이트의 오래된 데이터를 제거 할 수 있었으며 애플리케이션 로직을 단순화하는 동시에 연간 200,000 달러 이상의 비용을 절감했습니다.

추가 정보
TTL을 응용 프로그램에 사용할 때 염두에 두어야 할 몇 가지 사항이 있습니다.

  • TTL 속성 – TTL 속성은 색인화될 수 있지만 JSON 문서 요소가 될 수 없습니다. 이전에 언급했듯이, Number 데이터 유형이 있어야 합니다. 다른 속성과 마찬가지로 IAM을 사용하여 이 속성에 대한 접근 방식을 조절할 수 있습니다. 지정된 TTL 속성이 없는 항목은 삭제 대상이 아닙니다. 잘못된 TTL 값으로 인해 우발적인 삭제가 발생하지 않도록 5 년 이상인 항목은 삭제되지 않습니다.
  • 테이블 적용 내역 – 새 테이블 또는 기존 테이블에 TTL을 적용 할 수 있습니다. 표에 TTL을 사용하는 프로세스는 최대 한 시간이 걸릴 수 있으며 한 번에 하나의 표만 변경할 수 있습니다.
  • 백그라운드 처리 – 스캔 및 삭제는 백그라운드에서 수행되며 프로비저닝 된 처리량에 포함되지 않습니다. 삭제 시간은 만료 된 항목의 수와 특성에 따라 다릅니다. 만료 후 실제 삭제 전에 항목은 테이블에 남아 있으며 읽기 및 검색에 나타납니다.
  • 색인 방식 – 항목은 모든 로컬 보조 색인에서 즉시 제거되고 전역 보조 색인에서는 보통 일관된 방식으로 제거됩니다.
  • 가격 책정 – 내부 스캔 작업 또는 삭제 비용은 없습니다. 항목이 실제로 삭제 될 때까지 저장 비용을 지불하게됩니다.

정식 출시
본 기능은 오늘 부터 바로 사용하실 수 있으며, 자세한 사항은 DynamoDB Time to Live 가이드 문서를 참고하시기 바랍니다.

Jeff;

이 글은 New – Manage DynamoDB Items Using Time to Live (TTL)의 한국어 번역입니다.

Amazon DynamoDB 데이터 백업 및 복원 방법 – (2) 리전간 복제 기능을 활용한 데이터 이동

지난 번에 Amazon DynamoDB를 Export/Import 하는 두 가지 방법을 설명 드렸습니다. 즉,  AWS 관리 콘솔을 통해 DataPipeine과 EMR을 활용하는 방법과 github에 공개되어 있는 Import/Export Java Library를 이용하는 방법입니다.

이전 글에서는 Amazon DynamoDB 현재 저장 내용을 백업하는 용도라면, 이번 글은 원본 DynamoDB 테이블에 변경 내용만 다른 테이블에 지속적으로 복제(Replication)하는 방법을 안내해  드립니다.  이 방법은 공식 기술 문서에 따라 Github에 있는 소스 코드를 활용하는 것으로, 여기서 활용되는 리전간 복제 기능(Cross-region replication)은 기존 저장된 데이터를 읽어 옮기지는 않는다는 점에 유의하시기 바랍니다.

Amazon DynamoDB 리전간 복제 기능
Amazon DynamoDB 리전간 복제 기능은 자바(Java)로 개발되어 있습니다. 해당 라이브러리는 원본 DynamoDB ㅌ테이블에서 데이터 변경이나 새로운 데이터가 입력되면,  이동 대상 DynamoDB 테이블에 복제하는 기능을 합니다.  본  기능을 수행하는 라이브러리는 DynamoDB Stream을 통해 만들어졌으며,  이는 Amazon Kinesis를 활용하여  원본 테이블에서 변경된 정보를 Kinesis 스트림에 넣고 이를 가져와서 처리하거나 저장하게 됩니다.

본 기능을 잘 활용하면, 글로벌 멀티 플레이어 게임 서비스에서 각 리전(Region)에서 DynamoDB를  게임 마스터 DB로 사용할 경우,  다른 리전에서 업데이트 되거나 새로 입력된 데이터를 DynamoDB Stream을 통해 가져와  동기화할 수 있습니다. 또한, 변경되거나 새로 생성된 데이터를 DynamoDB Stream으로 받아 분석하거나 모니터링하는 용도로 활용 가능합니다.

또한, 이 도구는 병렬 처리를 지원합니다. 예를 들어, 매우 큰 사이즈의 DynamoDB 테이블의 경우 빠르게 옮기기 위해 이 도구를 여러 EC2 인스턴스에서 실핼 할 수도 있습니다. 이는 내부적으로 체크포인트(Checkpoint)를 사용하여 겹치지 않도록 병렬로 데이터를 옮길 수 있습니다. 병렬 처리 외에 복수 개의 DynamoDB 테이블도 지원합니다. 즉, 원본 테이블이 버지니아 리전에 있고, 서울 리전과 더블린 리전으로 복사하고 싶다면, 별도로 두 개의 프로세스를 실행 시켜서 복제가 가능합니다.

리전간 복제 라이브러리 설치
Amazon DynamoDB 리전간 복제 기능을 실행하기 위해서는 몇 가지 준비가 필요합니다. 우선 설치 후 실행할 리눅스 인스턴스가 필요합니다. 이 블로그에서는 Amazon Linux AMI를 이용하여 서울 리전에 인스턴스를 실행하여 설치하였습니다.

1. 빌드를 위해서는 메이븐(Maven)이 필요합니다. 메이븐을 받아 설치를 합니다. 다운로드 받은 후 원하는 위치에서 압축을 해제합니다. 보통 /usr/local 에 설치합니다. 메이븐 실행 파일인 mvn 을 실행하기 위해서 설치된 폴더 위치를 PATH환경 변수에 등록하여 줍니다. mvn 설치를 확인합니다.

$ wget http://ftp.kddilabs.jp/infosystems/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
$ tar -zxvf ./apache-maven-3.3.9-bin.tar.gz
$ export PATH=/usr/local/apache-maven-3.3.9/bin:$PATH
$ mvn --version
[ec2-user@ip-172-31-13-42 apache-maven-3.3.9]$ mvn --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)
Maven home: /usr/local/apache-maven-3.3.9
Java version: 1.7.0_111, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.111.x86_64/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.4.23-31.54.amzn1.x86_64", arch: "amd64", family: "unix"

2. 미리 Java JDK devel를 설치하여 mvn install 시에 중간에 에러가 없도록 준비합니다.

$ sudo yum install -y java-1.7.0-openjdk-devel

3. Github 의 소스를 Local로 가져옵니다. (만약 git이 설치되어 있지 않다면, sudo yum install git명령으로 먼저 설치합니다.)

$ git clone https://github.com/awslabs/dynamodb-cross-region-library.git

4. dynamodb-cross-region-libray가 복사된 폴더로 이동하여 아래 명령을 통해 빌드와 설치를 진행합니다.

$ sudo env "PATH=$PATH" mvn install
[ec2-user@ip-172-31-13-42 dynamodb-cross-region-library]$ mvn install
[INFO] Scanning for projects...
Downloading: https://repo.maven.apache.org/maven2/com/amazonaws/aws-java-sdk-bom/1.10.77/aws-java-sdk-bom-1.10.77.pom
Downloaded: https://repo.maven.apache.org/maven2/com/amazonaws/aws-java-sdk-bom/1.10.77/aws-java-sdk-bom-1.10.77.pom (14 KB at 9.7 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/com/amazonaws/aws-java-sdk-pom/1.10.77/aws-java-sdk-pom-1.10.77.pom
Downloaded: https://repo.maven.apache.org/maven2/com/amazonaws/aws-java-sdk-pom/1.10.77/aws-java-sdk-pom-1.10.77.pom (9 KB at 27.0 KB/sec)
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building DynamoDB Cross-region Replication 1.1.0
[INFO] ------------------------------------------------------------------------
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.7/maven-resources-plugin-2.7.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.7/maven-resources-plugin-2.7.pom (8 KB at 25.3 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/25/maven-plugins-25.pom
……………………………………
Downloaded: https://repo.maven.apache.org/maven2/org/codehaus/plexus/plexus-utils/3.0.5/plexus-utils-3.0.5.jar (226 KB at 719.0 KB/sec)
[INFO] Installing /usr/local/dynamodb-cross-region-library/target/dynamodb-cross-region-replication-1.1.0.jar to /root/.m2/repository/com/amazonaws/dynamodb-cross-region-replication/1.1.0/dynamodb-cross-region-replication-1.1.0.jar
[INFO] Installing /usr/local/dynamodb-cross-region-library/pom.xml to /root/.m2/repository/com/amazonaws/dynamodb-cross-region-replication/1.1.0/dynamodb-cross-region-replication-1.1.0.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 05:07 min
[INFO] Finished at: 2016-10-24T08:57:10+00:00
[INFO] Final Memory: 34M/128M
[INFO] ------------------------------------------------------------------------

데이터 복제 진행 여부 확인하기
원본 테이블에서 DynamoDB Stream을 활성합니다. 테이블은 이전 블로그 테이블을 활용하였습니다.

새로 저장될 테이블은 DynamoDB-replica1으로 원본 테이블과 동일한 Partition key(resource), Sort key를 설정하여 테이블을 생성합니다.

최종 빌드 된 jar파일이 있는 폴더로 이동하여 Github에 나온 안내를 참고하여 필요한 인자(Argument)를 주어 실행합니다. 위에서 설명드린 것처럼 버지니아 리전에 있는 Kinesis-Data-Visualization-CountsDynamoDBTable-49AHMYW180WC 테이블을 원본 테이블로 지정하고, 버지니아 리전에 DynamoDB-replica1이라는 테이블로 복제하는 명령의 예제입니다. 아래 명령은 실행된 후에 스탠드얼론(Standalone)으로 계속 실행 중이 됩니다.

$ sudo java -jar dynamodb-cross-region-replication-1.1.0.jar --sourceEndpoint dynamodb.us-east-1.amazonaws.com --sourceTable Kinesis-Data-Visualization-CountsDynamoDBTable-49AHMYW180WC --destinationEndpoint dynamodb.us-east-1.amazonaws.com --destinationTable DynamoDB-replica1

원본 테이블에 데이터를 하나 생성하여 입력합니다.

DynamoDB-replica1에 해당 아이템이 생성되었는지 확인합니다.

2회에 걸쳐 Amazon DynamoDB의 내용을 백업 및 복원, 그리고 변경이나 새로운 데이터를 바로 복제하는 방법을 알아 보았습니다. 글로벌 게임 개발 시 다양한 시나리오 따라 활용 사례가 많으므로 도움이 되시길 바랍니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 김일호 솔루션즈 아키텍트께서 작성해주셨습니다.

Amazon DynamoDB 데이터 백업 및 복원 방법 – (1) Datapipeline 및 오픈 소스 도구 활용하기

Amazon DynamoDB는 서비스 규모와 관계없이 10밀리초 미만의 지연 시간이 일관되게 요구되는 모든 애플리케이션을 위한 빠르고 유연한 NoSQL 데이터베이스 서비스입니다. 또한, 완전 관리형 클라우드 데이터베이스로서 문서 모델과 키-값 스토어 모델을 모두 지원합니다. 특히, 유연한 데이터 모델과 안정적인 성능을 갖추고 있어 모바일, 웹, 게임, 광고 기술, IoT를 비롯한 그 밖의 많은 애플리케이션에 매우 적합합니다.

특히 Amazon DynamoDB는 AWS 리전의 세 개 시설에 데이터를 동기적으로 적재하는 구조를 가지고 있어, 매우 높은 가용성과 데이터 안정성을 제공합니다. 따라서, 데이터 유실에 대한 우려를 크게 낮출 수 있습니다. 그런데, 필요에 따라서 DynamoDB에 저장되어 있는 데이터를 백업하거나 다른 리전으로 복사해야 할 필요가 생길 수 있습니다. 이는 전통적인 데이터 유실에 대한 데이터 백업이나 복원 목적이라기 보다는 로컬에서 데이터 활용을 하거나, 타 리전에 데이터 이동에 목적으로 생각할 수 있습니다.

이 글에서는 DynamoDB에 저장된 데이터를 백업하는 몇 가지 방법을 알아보도록 하겠습니다. Amazon DynamoDB를 이용하여 테이블(Table)을 생성하면 DynamoDB는 직접 내보내기 및 가져오기 기능을 제공하고 있습니다. 원하면 언제든지 테이블의 내용을 백업하거나, 백업한 테이블의 내용을 다른 테이블로 넣을 수 있습니다.

DynamoDB 내보내기(Export) 기능
먼저 테이블 내보내기 기능 부터 살펴 보겠습니다. 아래의 그림과 같이 원하는 테이블을 선택하고 Export를 실행하면됩니다.

dynamodb-image003

DyanmoDB의 내보내기 기능은 AWS의 다른 서비스 중 하나인 AWS Data Pipeline을 이용합니다. Data Pipeline은 Amazon EMR을 실행하도록 되어 있으며, 바로 EMR Cluster를 생성하고 생성된 EMR Hadoop Cluster가 바로 DyanmoDB의 데이터를 가져오는하는 작업(Job)을 실행하는 구조로 되어 있습니다.

AWS Data Pipeline은 DynamoDB 테이블 백업 뿐만 아니라 온프레미스 데이터 소스 및 다른 AWS 컴퓨팅 및 스토리지 서비스 간에 데이터를 안정적으로 지정된 간격으로 이동할 수 있게 해 주는 서비스입니다. AWS Data Pipeline을 사용하면 저장 데이터에 정기적으로 접근하고, 데이터 크기를 변환 처리하며 Amazon S3, Amazon RDS, Amazon DynamoDB 및 Amazon Elastic MapReduce(EMR)와 같은 AWS 서비스에 그 결과를 효율적으로 전송할 수 있습니다.

DynamoDB에서도 테이블을 선택하고 내보내기(Export)를 누르면 아래와 같이 새로운 파이프라인(Pipeline)을 생성합니다. 테이블의 내용을 바로 Amazon Simple Storage Service(S3)에 저장합니다.

dynamodb-image005

Source DynamoDB table name은 내보내고 싶은 테이블명으로 자동으로 입력이 되어 있습니다. Output S3 folder는 내보내기 후 데이터가 저장될 S3 버킷 폴더를 지정합니다. DynamoDB read throughput ratio는 현재 소스가 되는 DynamoDB의 읽기 용량 중에 어느 정도 비율을 사용할지 지정하는 중요한 파라미터입니다. 만약 운영 중인 서비스의 테이블이라면 읽기 용량의 일부를 지정한 비율만큼 내보내기 작업에 사용하므로, 너무 큰 비율을 지정하면 읽기 용량이 모자라게 되면 서비스에 영향이 있으므로 주의하여야 합니다.

따라서, Consumed read capacity unit을  CloudWatch 통계치를 확인하여 적절한 비율을 입력하도록 합니다. 위의 예제에서는 0.25로 기본 값이 지정되어 있습니다. 즉, Provisioned Read Capacity Unit중에 약 25%를 내보내기를 하는데 사용합니다. Throughput ratio를 정식 서비스 환경에서는 항상 유의하여 지정해야만 합니다. Region은 DynamoDB 테이블이 있는 리전을 선택합니다. Schedule은 Data Pipeline에서 바로 실행할지, 아니면 특정 시기/시간에 주기적으로 실행할지 여부를 구성합니다.

주기적으로 실행하도록 구성하면 Data Pipeline이 알아서 주기적으로 DynamoDB 테이블 내보내기를 진행하여 운영에 편의성을 제공합니다. Logging은 Log 내용을 남길 S3 위치를 지정하게 됩니다. 뒤에 작업(Job)이 실패했을 경우 문제가 어떤 것인지 찾을 수 있도록 로그 정보를 제공합니다.

Activate를 눌러 다음으로 진행하면 Data Pipeline이 생성됩니다. Data Pipeline은 EMR Cluster를 생성하고 데이터 내보내기를 진행하게 됩니다.

dynamodb-image007

위 그림과 같이 작업이 끝나게 되면 Status가 FINISHED로 상태가 바뀌게 되며, Logs에서 작업 중에 남겨진 로그 내용을 직접 확인할 수도 있습니다. 위 예제에서 s3://ilho-virginia-01 S3 Location을 설정 하였으므로 해당 버킷 밑에서 백업된 파일을 직접 확인할 수 있습니다.

dynamodb-image009

작업이 일어난 시간으로 폴더가 생성되고 내보내기한 파일이 조금 복잡한 이름으로 생성되어 저장이 되어 있습니다. 나중에 해당파일을 직접 접근할 때는 manifest파일을 보면 안에 해당 파일에 대한 s3 주소가 저장되어 있어, 직접 확인하지 않고도 접근할 수도 있습니다. 아래는 내보낸 DynamoDB 테이블 데이터 내용입니다. (예제는 웹페이지의 레퍼러(referrer)를 저장한 테이블입니다.)

dynamodb-image011

파일을 열어보면 아래와 같이 JSON 형태로 저장되어 있는 것을 확인 하실 수 있습니다. 따라서, 해당 파일을 데이터 분석과 같은 다른 용도로 사용할 경우, 빠르게 활용할 수 있습니다.

dynamodb-image013

DynamoDB Import 기능 소개
내보내기 파일을 이용하여 새로운 DynamoDB Table에서 해당 데이터를 가져오기(Import)할 수 있습니다. 단, 동일한 키(key)를 가지도록 먼저 대상 테이블(Target table)을 생성하고 가져와야 합니다. 따라서, 먼저 테이블을 생성하고, Primary Partition key, Primary Sort key를 동일하게 설정하여 새로운 테이블을 만듭니다.

아래와 같이 Import-test라는 테이블을 만들고 resource, timestamp를 Partition key와 Sort key로 지정하였습니다. 한가지 고려할 사항은 처리 용량(Provisioned Capacity)을 지정할 때 기본 값보다는 쓰기 용량(Write Capacity units)을 크게 지정하여 가져오기 하는 시간을 단축할 수 있습니다.

dynamodb-image015

새로 생성된 테이블을 선택하고 Import를 메뉴에서 선택합니다. 역시 Data Pipeline을 설정하는 페이지가 열리면서 내보내기할 때와 비슷한 내용을 입력합니다. 단, Import 이므로 반대로 Input S3 folder로 Export에 백업 파일이 있는 위치를 입력합니다. 내보내기할 때는 읽기 용량(Read capacity)사용에 대한 비율을 지정하였으나, 가져오기에서는 반대로 쓰기 용량(Write capacity)에 대해서 설정을 합니다. 새로 만든 테이블이므로 최대한 빠르게 가져오기를 진행하려면 100%로 지정하여, 모든 Write capacity를 가져오기에 사용할 수 있습니다. 단, 이는 예제이므로 서비스 상황에 따라 설정하여 사용합니다.

dynamodb-image017

설정 후에 Activate를 진행하면 Data Pipeline이 생성되고 EMR Cluster를 생성하여 S3에 Export된 데이터로부터 DynamoDB Table에 데이터를 넣는 작업(Job)을 실행합니다. Job이 FINISHED로 끝난 것을 확인하고 대상이 되는 Table에 실제 데이터가 들어왔는지 확인합니다.

dynamodb-image019

테이블에 데이터가 입력된 것을 확인 할 수 있으며, CloudWatch 통계에서 읽기 처리 그래프(Write Capacity Graph)를 보면 입력한 것처럼 전체 읽기 용량을 이용하여 데이터 가져오기 작업을 진행한 것을 확인 할 수 있습니다. (본 예제에서는 쓰기 용량(Write capacity) 값을 100으로 미리 설정(Provisioning)하고, 일정시간 동안 100의 용량이 소모된 것을 볼 수 있습니다.)

dynamodb-image021

한 가지 유의하실 것이 있습니다. DynamoDB의 Table 설명 정보에는 Storage size와 Item count 정보가 있습니다. 이 정보는 현재는 약 6시간 주기로 업데이트 되는 정보로 가져오기를 끝내자 마다 해당 정보 내용을 확인하신다면, 아직 0으로 표기가 되어 있게 됩니다. 따라서 실제 데이터를 직접 읽어 확인해 보는게 필요합니다. AWS CLI에서 보면 아래와 같이 확인이 가능합니다. 참고하여 주십시오.

$ aws dynamodb describe-table --table-name Import-test --query 'Table.{Count:ItemCount,Size:TableSizeBytes}'
{
    "Count": 0,
    "Size": 0
}
$ aws dynamodb scan --table-name Import-test --max-item 2
{
    "Count": 2777,
    "Items": [
        {
            "timestamp": {
                "S": "2014-12-15T12:49:10.147Z"
            },
            "host": {
                "S": "ip-10-97-166-72"
            },
            "resource": {
                "S": "/index3.html"
            },
            "referrerCounts": {
                "S": "[{\"referrer\":\"http://www.yahoo.com\",\"count\":3},{\"referrer\":\"http://www.reddit.com\",\"count\":1},{\"referrer\":\"http://www.bing.com\",\"count\":1},{\"referrer\":\"http://www.amazon.com\",\"count\":1}]"
            }
        },
        {
            "timestamp": {
                "S": "2014-12-15T12:49:10.247Z"
            },
            "host": {
                "S": "ip-10-97-166-72"
            },
            "resource": {
                "S": "/index3.html"
            },
            "referrerCounts": {
                "S": "[{\"referrer\":\"http://www.yahoo.com\",\"count\":3},{\"referrer\":\"http://www.reddit.com\",\"count\":1},{\"referrer\":\"http://www.bing.com\",\"count\":1},{\"referrer\":\"http://www.amazon.com\",\"count\":1}]"
            }
        }
    ],
    "NextToken": "eyJFeGNsdXNpdmVTdGFydEtleSI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9",
    "ScannedCount": 2777,
    "ConsumedCapacity": null
}

DynamoDB Import Export 도구
AWS 콘솔에서 제공하는 가져오기 및 내보내기 기능이 아닌 오픈 소스로 제공되는 https://github.com/awslabs/dynamodb-import-export-tool이 Github에 공개되어 있습니다. 간략히 설명 드리면, Java로 개발된 도구로 Data Pipeline이나 EMR을 사용하지 않고, 프로그램이 직접 DynamoDB의 데이터를 가져와서 타겟 DynamoDB Table에 데이터를 넣어주는 일을 하게 됩니다. 또한 병렬 검색(Parallel Scan)을 지원하여, 단일 EC2 인스턴스가 아닌 여러 인스턴스를 사용하여 병렬로 작업이 가능합니다. 아래 예제는 Amazon Linux AMI를 이용해 새로운 인스턴스를 생성하고 백업 및 복원을 진행 하는 방법입니다.

  1. 빌드를 위해서는 maven이 필요합니다. Maven을 받아 설치를 합니다.
    $ wget http://ftp.kddilabs.jp/infosystems/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
    $ tar -zxvf ./apache-maven-3.3.9-bin.tar.gz
  2. 미리 Java JDK를 설치하여 mvn install 시에 중간에 에러가 없도록 준비합니다.
    $ sudo yum install -y java-1.7.0-openjdk-devel
  3. Github 의 소스를 Local로 가져옵니다.
    $ git clone https://github.com/awslabs/dynamodb-import-export-tool.git
  4. 아래 명령을 통해 빌드와 설치를 진행합니다.
    $ mvn install
    ……………………………………
    [INFO] Replacing /opt/dynamodb-import-export-tool/target/dynamodb-import-export-tool-1.0.1.jar with /opt/dynamodb-import-export-tool/target/dynamodb-import-export-tool-1.0.1-shaded.jar
    [INFO]
    [INFO] --- maven-gpg-plugin:1.6:sign (sign-artifacts) @ dynamodb-import-export-tool ---
    Downloading: https://repo.maven.apache.org/maven2/org/sonatype/plexus/plexus-sec-dispatcher/1.4/plexus-sec-dispatcher-1.4.pom
    Downloaded: https://repo.maven.apache.org/maven2/org/sonatype/plexus/plexus-sec-dispatcher/1.4/plexus-sec-dispatcher-1.4.pom (3 KB at 9.9 KB/sec)
    Downloading: https://repo.maven.apache.org/maven2/org/sonatype/plexus/plexus-sec-dispatcher/1.4/plexus-sec-dispatcher-1.4.jar
    Downloaded: https://repo.maven.apache.org/maven2/org/sonatype/plexus/plexus-sec-dispatcher/1.4/plexus-sec-dispatcher-1.4.jar (28 KB at 90.8 KB/sec)
    [INFO]
    [INFO] --- maven-install-plugin:2.4:install (default-install) @ dynamodb-import-export-tool ---
    [INFO] Installing /opt/dynamodb-import-export-tool/target/dynamodb-import-export-tool-1.0.1.jar to /root/.m2/repository/com/amazonaws/dynamodb-import-export-tool/1.0.1/dynamodb-import-export-tool-1.0.1.jar
    [INFO] Installing /opt/dynamodb-import-export-tool/pom.xml to /root/.m2/repository/com/amazonaws/dynamodb-import-export-tool/1.0.1/dynamodb-import-export-tool-1.0.1.pom
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 34.017 s
    [INFO] Finished at: 2016-08-01T01:12:26+00:00
    [INFO] Final Memory: 20M/50M
    [INFO] ------------------------------------------------------------------------
  5. 최종 빌드 된 jar파일이 있는 폴더로 이동하여 Github에 나온 안내를 참고하여 필요한 인자(Argument)를 주어 실행합니다. 아래 예제는 버지니아 리전에 있는 Kinesis-Data-Visualization-CountsDynamoDBTable-49AHMYW180WC 테이블을 동일한 리전에 Kinesis-target-3이라는 테이블로 복제하는 명령입니다. 이 도구에서도 읽기 혹은 쓰기 용량(read/write capacity)에 대해서 비율를 지정하여 얼마만큼의 Provisioned Capacity를 사용할지 지정을 하게 됩니다. 여기서는 1로 지정하여 100%를 다 사용하도록 지정하였습니다.
    $ java -jar dynamodb-import-export-tool-1.0.1.jar --sourceEndpoint dynamodb.us-east-1.amazonaws.com --sourceTable Kinesis-Data-Visualization-CountsDynamoDBTable-49AHMYW180WC --destinationEndpoint dynamodb.us-east-1.amazonaws.com --destinationTable Kinesis-target-3 --readThroughputRatio 1 --writeThroughputRatio 1

앞서 말씀 드린 대로 Amazon DynamoDB는 고가용성과 안정성을 지원하도록 디자인된 관리형 서비스입니다. 가용성 측면보다 데이터 활용 측면에서 데이터 이동이 필요한 경우에는 Datapipeline을 통한 DynamoDB 가져오기 및 내보내기 기능 및 오픈 소스 도구를 활용할 수 있습니다.

또한, DynamoDB Stream을 통한 크로스 리전 복제 솔루션 역시 사용이 가능합니다. 다음에는 오픈 소스로 공개되어 있는 DynamoDB Cross-Region Replication Library를 통해 실시간 복제 방법에 대해서 알아보겠습니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 김일호 솔루션즈 아키텍트께서 작성해주셨습니다.

신규 Logstash 플러그인 – Elasticsearch를 이용한 DynamoDB 검색 기능

최근 서비스 출시 소식을 보자면 GitHub에서 AWS 관련 리포지터리와 결합하면 재미있는 경향이 나타납니다. 다른 회사 개발 도구에 AWS 서비스를 연결하는 것이 일반화 되고 있기 때문입니다. 예를 들어,
이벤트 데이터 시각화를 위한 CloudWatch Logs, Elasticsearch, 및 Kibana 연결 방법이나 AWS OpsWorks와 ECS 콘테이너 관리 등이 좋은 사례입니다.

DynamoDB + Elasticsearch
오늘 Logstash에서 DynamoDB Streams connector (plugin)을 통해 DynamoDB와 Elasticsearch를 연결하는 방법을 소개하고 싶습니다. Logatash는 Amazon Elastic Compute Cloud (EC2) 인스턴스 또는 온 프레미스 환경에서 실행할 수 있습니다. DynamoDB 테이블과 Streams에서 입력 정보를 받도록 설정한 뒤 테이블에 대한 변경(추가, 업데이트, 삭제)을 추적하고 그에 따라 Elasticsearch 클러스터를 갱신합니다. 테이블과 동기화하려면 클러스터를 이용하여 테이블을 스캔하도록 플러그인을 구성 할 수도 있습니다.

일단 클러스터가 올라가고, 실행 테이블의 변경 내용 추적이 시작되면 Elasticsearch를 이용하여 효율적인 쿼리(structured, full-text, 및 multifield)를 수행 할 수 있습니다. 쿼리를 사용하여 proximity matching(근접 일치)과 partial matching(부분 일치)을 이용할 수 있으며, 또한 Elasticsearch 스코어링 인프라를 사용하여 관련성을 제어 할 수 있습니다. (더 자세한 것은 Elasticsearch : The Definitive Guide를 참고하세요.)

DynamoDB 테이블에 대한 변경은 매우 빠르게 (1 초 미만) Stream에 반영됩니다. 플러그인은 이러한 변화에 액세스 할 수있게 가능한 한 신속하게 클러스터를 업데이트합니다.

다운로드 및 사용하기

DynamoDB Community에서 플러그인을 다운로드하여 EC2 인스턴스에 설치하고 Elasticsearch 클러스터에서 DynamoDB의 콘텐츠 검색을 시작할 수 있습니다. 더 자세한 사항은 개발자 문서를 참고하시고, awslabs Github의 README를 따라 설치해 보실 수 있습니다.

Jeff;

이 글은 New Logstash Plugin – Search DynamoDB Content using Elasticsearch의 한국어 번역입니다.

DynamoDB 신규 기능 – 스트림 및 Lambda 데이터 트리거 + 리전간 복제

Amazon DynamoDB에 여러 가지 새로운 소식이 있습니다. 먼저 DynamoDB 스트림 기능이 추가되었으며, AWS Lambda를 통해 스트림 데이터 활용이 가능합니다. 두 번째는 하나의 DynamoDB 테이블에서 다른 테이블로 복제가 가능하고, 리전(Regions)을 넘어서도 가능해졌습니다.

지금 부터 자세히 살펴 보겠습니다.

DynamoDB Streams
지난 가을에 re:Invent 행사 며칠 전 DynamoDB 스트림에 대한 미리 보기 기능을 출시했습니다. 많은 사용자들이 DynamoDB 테이블의 변경을 추적하기를 원하셨기 때문이었습니다.

이 기능은 오늘부터 정식으로 사용할 수 있으며, 바로 DynamoDB 테이블에 기능을 활성화하면 모든 변경 사항(put, update, delete)를 24시간 언제든지 stream record로서 실시간으로 스트리밍으로 받을 수 있습니다. 여러 개의 스트림 레코드는 빠르고 효율적인 처리를 위해 샤드(shard)에 그룹으로 만들어서 하나의 단위로 변환됩니다.

테이블 변경 순서의 상대적인 위치는 하나의 고유키로 만들어서 샤드안에 저장됩니다. 이를 통해 항목 변화를 정확히 추적할 수 있도록 샤드 내에 스트림 레코드를 쉽게 처리할 수 있게 됩니다.

“Interactive Intelligence는 Amazon DynamoDB의 리전간 복제 기능을 처음 테스트 해보고 매우 놀라웠습니다. PureCloud 플랫폼이 이 기능을 처음 도입을 해보고, 빠르고 쉽게 AWS 리전간 데이터가 쉽게 복제되어서 운영 및 기술 지원 비용을 확실히 감소할 수 있게 되었습니다.”
Mike Szilagyi, PureCloud Service Technology 부사장
Interactive Intelligence

프로그램 코드를 사용해서 샤드에서 레코드를 추출한 후, 변환 받은 다음 필요한 기능을 수행할 수 있습니다. 각 레코드는 미리 생성된 테이블 쓰기 용량 내에서 두 번 정도에 변환 받을 수 있습니다.

스트림 기능을 활성화하려면, 테이블을 만들 때 CreateTable를 호출하여 스트림에 대한 파라미터를 넣어 만들 수 있습니다. 기존 테이블에서도 UpdateTable에서 비슷한 파라미터를 넣으시면 됩니다. 각각의 경우, 표준 스펙에 스트림을 시작할지 말지에 대한 플래그(flag)와 보기 형식(저장 및 반환 항목키 만, 새로운 이미지, 예전 이미지 혹은 둘 다)를 포함해야 합니다.

좀 더 자세한 사항은 신규 기능에 대한 DynamoDB Streams Developer Guide를 참고하시기 바랍니다.

추가 비용 없이 여러분의 테이블에 스트리밍 기능을 바로 만드실 수 있으며, 스트림에서 데이터를 읽을 때만 과금이 되는데 GetRecords를 통한 호출 시 1MB까지 데이터를 꺼내 올 수 있습니다. 좀 더 자세한 것은 요금 정책을 참고하시면 됩니다.

DynamoDB 스트림 + Lambda = 데이터베이스 트리거
AWS Lambda는 (현재 Node.js와 자바)를 통해 만든 프로그래밍 코드를 클라우드 내에서 실행하는 신개념의 클라우드 함수입니다.  장애나 확장성에 대한 고려 없이도 100 밀리초 단위로 실행한 시간 만큼만 과금을 하는 경제적인 모델을 가진 서비스입니다.

오늘 DynamoDB 스트림 기능을 정식 출시함으로서 테이블이 더 커지거나 쿼리가 많아질 때, 확장성을 고려하지 않고도 기존의 프로그래밍 코드보다 훨씬 적은 노력만으로 (Lambda를 이용하여) 스트림 레코드를 처리할 수 있습니다.

즉,  이 두 가지를 조합해서 간단한 NoSQL 스타일의 데이터베이스 트리거를 만들 수 있습니다. 예전에 관계형 DB의 트리거는 엔진 내에서 구현되었고, 때문에 엔진에서 정의된 동작만 수행할 수 있는 제한이 있었습니다. Lambda를 이용하면, 데이터 추가, 삭제 및 테이블 항목 변경이 일어날 때 마다 관련되는 동작을 원하는 대로 구현할 수 있습니다. 신규 혹은 과거 이미지의 변경 사항을 분석하고, 데이터 양식을 변경하거나 특정 비지니스 로직을 동기 혹은 비동기로 강제하는 것도 가능합니다. 여러분이 좀 더 애플리케이션 개발에 중요한 부분에 집중하도록 Lambda를 통해 호스팅과 확장 문제를 관리하게 만들어 둘 수도 있습니다.

Lambda 코드를 설정해서 스트림 변경을 확인하는 것도 간단합니다. 새 테이블을 통해 하는 방법을 간단히 살펴 보겠습니다. 먼저 Lambda를 위한 IAM 역할을 만들고, 관리 콘솔에서 Create Lambda function을 실행해 봅니다. 예제들 중 dynamodb-process-stream를 선택해 보겠습니다.

먼저 Lambda 함수 예제 코드와 이벤트 소스를 설정합니다.콘솔 화면에 이벤트 소스로 user_table이라는 테이블을 연결해서, 100개까지의 스트림 레코드를 받아서 새로운 레코드로 처리하는 기능을 수행해 보겠습니다.

예제에는 현재 상태를 테스트해 보는 목적의 코드가 있으며, 간단한 이름을 정한 후 (ProcessUserTableRecords) DynamoDB에 접근할 수 있는 IAM 역할을 선택합니다.

이제 이벤트 소스를 활성화 해보겠습니다. (Lambda 코드를 테스트해 본 후에 실제 동작 하도록 하는 게 좋습니다.)

Create function을 눌러서 이벤트 소스로서 테이블 업데이트 스트림을 처리하는 함수를 만듭니다. Lambda 콘솔의 Event sources탭에서 상태와 다른 이벤트 소스도 보실 수 있습니다.

자, 이제 설정이 다 끝났고 여기서 테이블의 업데이트 스트림을 연결 한 후, 레코드를 처리해 봅시다. 이를 위해 DynamoDB 콘솔로 옮겨가서 데이터를 몇 개 추가해서 스트림에 변화가 생기도록 해 보겠습니다.

Lambda 콘솔에 들어와 보면, 기대했던 동작이 일어났는지 확인해 볼 수 있습니다. 모니터링 탭을 클릭해 보면 오류 없이 Lambda 함수가 두 번 실행된 것을 알 수 있습니다.

일단 잘 동작한 것으로 보고 CloudWatch 로그를 좀 더 자세히 보겠습니다.

만약 제가 실제 애플리케이션을 만들었다면, 기본 예제에 더 많은 기능을 추가해서 만들어 볼 수 있었을 것입니다.

AWS 고객인 Mapbox는DynamoDB Streams와 Lambda를 이용한 후기를 Scaling the Mapbox Infrastructure with DynamoDB Streams를 통해 소개하였습니다.

DynamoDB와 Lambda를 결합한 구현 방식에 대해서는 Using DynamoDB Streams and AWS Lambda 문서를 참고하시기 바랍니다. DynamoDB Trigger에는 추가 요금이 없고 Lambda 함수 실행에 대한 과금만 이루어 지며 자세한 것은 Lambda 요금 정보를 참고하시기 바랍니다.

이러한 조합을 통해 여러분의 애플리케이션이 더 간단하고 강력하며 반응성이 높은 기능을 추가할 수 있기를 기대해 봅니다.

리전(Region)간 DynamoDB 복제 기능
DynamoDB 스트림 기능과 아울러 AWS 리전 간 데이터를 쉽게 복제할 수 있는 기능을 소개해드립니다. 이 애플리케이션은 작년에 저희가 배포한 DynamoDB Cross Region Replication library를 통해 구현한 것입니다. (앞으로도 이 라이브러리를 여러분의 앱에 사용하셔도 됩니다.)

이를 통해 DynamoDB를 여러개의 리전으로 중복으로 복제할 수 있는데, 이는 재난 복구나 여러 지역에서 낮은 지연을 통해 접근이 필요한 여러가지 이유가 있을 수 있습니다. 보시다시피 아주 간단하게 리플리카를 만들어서 운영할 수 있게 됩니다.

이 앱은 AWS Elastic Beanstalk에서도 실행할 수 있고, Amazon EC2 Container Service를 사용할 수 있으며, AWS CloudFormation 템플릿으로도 구현 가능합니다. DynamoDB 콘솔에서 초기화 할 수 있으며 CloudFormation을 통해 스택이나 콘테이너를 생성하기 위한 템플릿 정보를 입력할 수 있습니다.

스택(Stack, 템플릿을 통해 만들어지는 AWS 자원에 대한 이름)을 입력하고 Next를 눌러 파라미터를 입력할 수 있습니다. (대부분 기본값을 그대로 두시면 됩니다.)

메타테이터 테이블은 복제에 필요한 정보를 포함합니다. 이는 어떤 테이블을 복제할 것인지 어디에 저장할 것인지를 설정합니다. 복제용 앱을 띄운 후, 온라인 설정 화면에 접속하술 수 있습니다. (CloudFormation 템플릿이 URL을 만들어 줍니다.)

이 기능 또한, 추가 요금이 없습니다. 이 기능을 활용하기 위한 기본적인 DynamoDB 리소스(미리 설정된 입출력 한도, 복제 테이블의 저장 용량, 리전간 데이터 전송 비용, 스트림으로 데이터 읽기 및 애플리케이션을 제어하는데 필요한 EC2 인스턴스 및 SQS 서비스 이용 비용 등)에 대해서만 과금이 됩니다. 더 자세한 것은 DynamoDB 요금페이지를 참고하시기 바랍니다.

리전 간 복제에 대한 더 자세한 정보는 Cross Region Replication를 참고하시기 바랍니다.

Jeff;

이 글은 DynamoDB Update – Triggers (Streams + Lambda) + Cross-Region Replication App의 한국어 번역입니다.