ちょっと話題の記事

DynamoDB全くわからない、から、ちょっとわかるようになるまでの道しるべ

2019.07.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

DynamoDBを利用するためのポイントをざっくりまとめた。

リンク集みたいな感じになっていますが、どこから手をつけて良いかわからない方は参考にしてみてください。

目次

DynamoDB概要

Amazon DynamoDB は、どのような規模でも信頼性が高いパフォーマンスを維持できる、非リレーショナルデータベースです。 完全マネージド型、マルチリージョン、マルチマスターのデータベースで、レイテンシーを 10 ミリ秒未満に維持でき、 組み込みのセキュリティ、バックアップと復元、インメモリキャッシュを利用できます。

DynamoDBの特徴

  • フルマネージドサービス
  • データの格納と取得に特化(高度な最適化)されている
  • 表結合など柔軟なクエリを発行するのは不得意
  • 「値」とそれを取得するための「キー」だけを格納するというシンプルな機能を持った「Key-Valueストア」
  • 半構造化データをドキュメントとして保存する「ドキュメントデータベース」でもある
  • 1桁ミリ秒単位のレイテンシーを要求するアプリケーションにも対応
  • 期限切れになった項目を自動的にテーブルから削除することも可能

一般的なユースケース

DynamoDBは以下がの要件をもつシステムと相性が良いです。

  • ミリ秒単位のアクセスレイテンシーが求められる
  • データの拡張性が求められる

そのためモバイル、ウェブ、ゲーム、広告技術、IoTのようなサービスのバックエンドとしてよく利用されています。

具体的なユースケースについては以下をご確認ください。

また、Lambdaとも相性が良くAPIGateway+Lambdaと合わせて利用されることが多いです。

コスト

DynamoDBの料金を決める要素は大きく3つです。

  • キャパシティーユニット
  • ストレージ容量
  • データ転送量

以下のブログを読みどのような計算になるのか大枠で理解しておいてください。

ある程度トラフィックが予想できる場合は、キャパシティーの設定方法は「プロビジョニング」とするのがコスト効率が良いです。 アクセスが大きく変動する場合には、「AutoScaling」や「DynamoDB On-Demand」という選択肢もあります。

「DynamoDB On-Demand」 は便利な機能ですが、突発的なアクセスがきた場合のAWS利用費について意識しておく必要があります。

バックアップ

DynamoDBはオンデマンドバックアップと継続的バックアップの2種類の方法でバックアップを取得することができます。

以下のブログを読み概要を理解してください。

DynamoDBとうまく付き合うために

まずはDynamoDBに触れてみる

DynamoDBを触ったことがない方は以下のブログを一通り実施し、DynamoDBの簡単な使い方を理解してください。

バックエンドのアーキテクチャを理解する

DynamoDBを効率的に使うためにはバックエンドのアーキテクチャを知っておくことが大切です。 古い記事になりますが、以下の記事を読み概念を理解してください。

  • ハッシュキー → パーティションキー
  • レンジキー → ソートキー

にそれぞれ読み替えてください。

テーブルの設計方法を理解する

DynamoDBにおけるテーブル設計はRDBMSとは違います。DynamoDBにおけるテーブル設計を理解しましょう。

プログラムからDynamoDBにデータを格納してみる

最後に簡単なスクリプトを使ってDynamoDBにデータを格納してみましょう!

S3へのPutをトリガーにLambdaを実行し、S3に格納されたファイルの内容をDynamoDBに書き込む仕組みを構築します。

  • DynamoDB作成(CloudFormation)
  • S3、Lambda作成(ServerlessFramework)
  • テスト

の順に実施していきます。

なお、S3にPutされるファイルは以下のような構造とします。

test.json

{
    "data": [
        {
            "month": "201907",
            "date": "30",
            "value": 10
        },
        {
            "month": "201907",
            "date": "31",
            "value": 20
        },
        {
            "month": "201908",
            "date": "01",
            "value": 30
        },
        {
            "month": "201908",
            "date": "02",
            "value": 40
        }

    ]
}

DynamoDB作成(CloudFormation)

CloudFormationの定義ファイルを作成します。

sample-dynamodb.yaml

Resources:
  DDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: "sample-table"
      AttributeDefinitions:
        -
          AttributeName: "month"
          AttributeType: "S"
        -
          AttributeName: "date"
          AttributeType: "S"
      KeySchema:
        -
          AttributeName: "month"
          KeyType: "HASH"
        -
          AttributeName: "date"
          KeyType: "RANGE"
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5

DynamoDBを作成します。

$ aws cloudformation create-stack --stack-name sample-dynamodb --template-body file://sample-dynamodb.yaml

$ aws dynamodb list-tables
{
    "TableNames": [
        "sample-table"
    ]
}

S3、Lambda作成(ServerlessFramework)

ServerlessFrameworkを使いS3をトリガーとする簡単なLambdaファンクションを作成します。

ServerlessFrameworkの使い方がわからない方は以下をご確認ください。

handler.pyserverless.ymlの2つのファイルを作成します。

$ ll
total 16
-rw-r--r--  1 jogan.naoki  staff   1.3K  7 12 14:49 handler.py
-rw-r--r--  1 jogan.naoki  staff   194B  7 12 16:04 serverless.yml

Lambdaファンクションを定義します。

handler.py

import json
import boto3
import logging
import urllib

import botocore.exceptions
from botocore.exceptions import ClientError

logger = logging.getLogger()
logger.setLevel(logging.INFO)

s3_client = boto3.client('s3')
dynamodb_resource = boto3.resource('dynamodb')
sample_table = dynamodb_resource.Table('sample-table')

def lambda_handler(event, context):

    logger.info('## event')
    logger.info(event)

    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8') 

    # S3のオブジェクトを取得
    sample_json_response = s3_client.get_object(Bucket = bucket, Key = key)

    logger.info('## sample_json_response')
    logger.info(sample_json_response)

    # jsonをパース
    sample_json = json.loads(sample_json_response['Body'].read().decode('utf-8'))
    
    # jsonのデータ数分ループしDynamoDBにPut
    for item in sample_json['data']:
        sample_table_put_item_response = sample_table.put_item(
            Item={
                'month': item['month'],
                'date': item['date'],
                'value': item['value']
            }
        )

        logger.info('## sample_table_put_item_response')
        logger.info(sample_table_put_item_response)

    response = {
        "statusCode": 200
    }
    return response

Lambda、S3をデプロイするための定義ファイルを作成します。 ※S3の名前は任意の値に変更してください。

対象のLambdaには以下の権限を付与します。

  • AmazonDynamoDBFullAccess
  • AmazonS3FullAccess

serverless.yml

service: sample-function

provider:
  name: aws
  runtime: python3.7
  region: ap-northeast-1
  iamManagedPolicies:
  - 'arn:aws:iam::aws:policy/AmazonS3FullAccess'
  - 'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess'
functions:
  dynamotest:
    name: sample-function
    handler: handler.lambda_handler
    events:
      - s3: XXXXXXXXXXXXX

Lambda、S3をデプロイします。

$ sls deploy -v
CloudFormation - CREATE_COMPLETE - AWS::S3::Bucket - XXXXXXXXXX
CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - sample-function-dev
CloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - sample-function-dev

テスト

S3にファイルをアップロードします。

$ aws s3 cp test.json s3://blog-jogan-20190712

すると、Lambdaが実行され

DynamoDBに値が格納されました。

さいごに

これであなたもDynamoDBちょっとわかるマン!!

DynamoDBはRDSと同じように使うことはできません。適材適所で正しく使っていきましょう!!