DynamoDB全くわからない、から、ちょっとわかるようになるまでの道しるべ
DynamoDBを利用するためのポイントをざっくりまとめた。
リンク集みたいな感じになっていますが、どこから手をつけて良いかわからない方は参考にしてみてください。
目次
DynamoDB概要
Amazon DynamoDB は、どのような規模でも信頼性が高いパフォーマンスを維持できる、非リレーショナルデータベースです。 完全マネージド型、マルチリージョン、マルチマスターのデータベースで、レイテンシーを 10 ミリ秒未満に維持でき、 組み込みのセキュリティ、バックアップと復元、インメモリキャッシュを利用できます。
DynamoDBの特徴
- フルマネージドサービス
- データの格納と取得に特化(高度な最適化)されている
- 表結合など柔軟なクエリを発行するのは不得意
- 「値」とそれを取得するための「キー」だけを格納するというシンプルな機能を持った「Key-Valueストア」
- 半構造化データをドキュメントとして保存する「ドキュメントデータベース」でもある
- 1桁ミリ秒単位のレイテンシーを要求するアプリケーションにも対応
- 期限切れになった項目を自動的にテーブルから削除することも可能
一般的なユースケース
DynamoDBは以下がの要件をもつシステムと相性が良いです。
- ミリ秒単位のアクセスレイテンシーが求められる
- データの拡張性が求められる
そのためモバイル、ウェブ、ゲーム、広告技術、IoTのようなサービスのバックエンドとしてよく利用されています。
具体的なユースケースについては以下をご確認ください。
また、Lambdaとも相性が良くAPIGateway+Lambdaと合わせて利用されることが多いです。
コスト
DynamoDBの料金を決める要素は大きく3つです。
- キャパシティーユニット
- ストレージ容量
- データ転送量
以下のブログを読みどのような計算になるのか大枠で理解しておいてください。
ある程度トラフィックが予想できる場合は、キャパシティーの設定方法は「プロビジョニング」とするのがコスト効率が良いです。 アクセスが大きく変動する場合には、「AutoScaling」や「DynamoDB On-Demand」という選択肢もあります。
- DynamoDB Auto Scaling によるスループットキャパシティの自動管理
- Amazon DynamoDB On-Demandをためしてみた! #reinvent | DevelopersIO
- Amazon DynamoDB On-Demand – 事前のキャパシティプランニングが不要のリクエスト課金が可能になりました。 | Amazon Web Services ブログ
「DynamoDB On-Demand」 は便利な機能ですが、突発的なアクセスがきた場合のAWS利用費について意識しておく必要があります。
- オンデマンドキャパシティーの料金 - Amazon DynamoDB | AWS
- Amazon DynamoDBをオンデマンド(従量課金)で利用した場合の料金体系まとめ #reinvent | DevelopersIO
- DynamoDBのオンデマンドとプロビジョニングの料金を比較をしてみた #reinvent | DevelopersIO
バックアップ
DynamoDBはオンデマンドバックアップと継続的バックアップの2種類の方法でバックアップを取得することができます。
以下のブログを読み概要を理解してください。
DynamoDBとうまく付き合うために
まずはDynamoDBに触れてみる
DynamoDBを触ったことがない方は以下のブログを一通り実施し、DynamoDBの簡単な使い方を理解してください。
バックエンドのアーキテクチャを理解する
DynamoDBを効率的に使うためにはバックエンドのアーキテクチャを知っておくことが大切です。 古い記事になりますが、以下の記事を読み概念を理解してください。
- ハッシュキー → パーティションキー
- レンジキー → ソートキー
にそれぞれ読み替えてください。
テーブルの設計方法を理解する
DynamoDBにおけるテーブル設計はRDBMSとは違います。DynamoDBにおけるテーブル設計を理解しましょう。
プログラムからDynamoDBにデータを格納してみる
最後に簡単なスクリプトを使ってDynamoDBにデータを格納してみましょう!
S3へのPutをトリガーにLambdaを実行し、S3に格納されたファイルの内容をDynamoDBに書き込む仕組みを構築します。
- DynamoDB作成(CloudFormation)
- S3、Lambda作成(ServerlessFramework)
- テスト
の順に実施していきます。
なお、S3にPutされるファイルは以下のような構造とします。
{ "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の定義ファイルを作成します。
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.py
とserverless.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ファンクションを定義します。
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
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と同じように使うことはできません。適材適所で正しく使っていきましょう!!