DynamoDB Accelerator(DAX)にEC2/Lambdaでアクセスする

DynamoDB Accelerator(DAX)にEC2/Lambdaでアクセスする

DynamoDB Accelerator(DAX)にEC2/Lambdaでアクセスする

AWS SAAの出題範囲の1つである、高性能なアーキテクチャの設計に関する内容です。

DynamoDB Accelerator(DAX)はDynamoDB用のキャッシュサービスです。

Amazon DynamoDB Accelerator (DAX) は、フルマネージド型高可用性インメモリキャッシュで、Amazon DynamoDB 用に特化しています。1 秒あたりのリクエスト数が数百万件になる場合でも、ミリセカンドからマイクロセカンドへの最大 10 倍のパフォーマンス向上を実現します。

Amazon DynamoDB Accelerator (DAX)

今回はDAXを作成し、EC2およびLambdaからアクセスすることを目的とします。

構築する環境

Diagram of accessing DynamoDB Accelerator (DAX) with EC2/Lambda.

VPC外にDynamoDBテーブルを作成します。
検証用アイテムを保存できるように、パーティションキー・ソートキー等を設定します。

プライベートサブネットにDAXクラスターを配置します。
クラスター内に2つのノードを配置します。
プライマリノードとリードレプリカノードです。

DAXクラスターにアクセスするクライアントとして、プライベートサブネット内に2つのリソースを作成します。

1つ目はEC2インスタンスです。
DAXクラスターに接続するためにAWS公式パッケージを使用します。
これをインストールするために、NATゲートウェイを経由して、インターネットにアクセスします。

2つ目はLambda関数です。
こちらもDAXクラスターに接続するために専用パッケージを使用しますので、Lambdaレイヤーという形で準備します。
なお関数のランタイム環境はPython3.8とします。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-saa/tree/main/02/009

テンプレートファイルのポイント解説

DAX

DAXを作成するためには、以下の4つのリソースを作成する必要があります。

  • DAXクラスター
  • パラメータグループ
  • サブネットグループ
  • IAMロール

DAXクラスター

Resources:
  DAXCluster:
    Type: AWS::DAX::Cluster
    Properties:
      AvailabilityZones:
        - !Sub "${AWS::Region}${AvailabilityZone1}"
        - !Sub "${AWS::Region}${AvailabilityZone2}"
      ClusterEndpointEncryptionType: NONE
      ClusterName: !Sub "${Prefix}-Cluster"
      Description: Test DAX Cluster
      IAMRoleARN: !GetAtt DAXRole.Arn
      NodeType: !Ref DAXNodeType
      ParameterGroupName: !Ref DAXParameterGroup
      ReplicationFactor: 2
      SecurityGroupIds:
        - !Ref DAXSecurityGroup
      SubnetGroupName: !Ref DAXSubnetGroup
Code language: YAML (yaml)

AvailabilityZonesプロパティで、クラスターを配置するAZを指定します。
クラスターを配置するAZに関して、AWS公式は以下の通り言及しています。

本稼働環境での使用においては、少なくとも 3 つのノードをそれぞれ異なるアベイラビリティーゾーンに置いて DAX を使用することを強くお勧めします。DAX クラスターが耐障害性を持つためには 3 つのノードが必要です。

DAX クラスターコンポーネント

今回は検証目的ですから、2つのAZにクラスターを配置することとします。

NodeTypeプロパティで、クラスター内のノードのインスタンスタイプを設定できます。
今回は最小サイズの「dax.t3.small」を指定します。

ReplicationFactorプロパティは、クラスター内のノード数を設定するものです。
今回はクラスター内に2つのノードを作成しますので、「2」を指定します。

SecurityGroupIdsプロパティでDAXクラスターに適用するセキュリティグループを指定します。
クラスターに適用するセキュリティグループに関して、AWS公式では、以下の通り言及されています。

VPC でクラスターを起動する際に、着信ネットワークトラフィックを許可する進入ルールをセキュリティグループに追加します。進入ルールは、クラスターのプロトコル (TCP) とポート番号 (8111) を指定します。

DAX クラスターコンポーネント

ですから今回は以下のセキュリティグループを適用します。

Resources:
  DAXSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-DAXSecurityGroup"
      GroupDescription: Allow DAX.
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: !Ref DAXPort
          ToPort: !Ref DAXPort
          SourceSecurityGroupId: !Ref InstanceSecurityGroup
        - IpProtocol: tcp
          FromPort: !Ref DAXPort
          ToPort: !Ref DAXPort
          SourceSecurityGroupId: !Ref FunctionSecurityGroup
Code language: YAML (yaml)

EC2インスタンスおよびLambda関数のセキュリティグループからの8111/tcpを許可する内容です。

パラメータグループ

パラメータグループに関して、AWS公式では以下の通り説明されています。

A named set of parameters that are applied to all of the nodes in a DAX cluster.

AWS::DAX::ParameterGroup
Resources:
  DAXParameterGroup:
    Type: AWS::DAX::ParameterGroup
    Properties:
      Description: Test DAX Parameter Group
      ParameterGroupName: !Sub "${Prefix}-ParameterGroup"
      ParameterNameValues:
        query-ttl-millis: 75000
        record-ttl-millis: 88000
Code language: YAML (yaml)

今回は上述ページを参考に設定しました。

サブネットグループ

サブネットグループは、クラスターを配置するサブネットを指定するリソースです。

Resources:
  DAXSubnetGroup:
    Type: AWS::DAX::SubnetGroup
    Properties:
      Description: Test DAX Subnet Group
      SubnetGroupName: !Sub "${Prefix}SubnetGroup"
      SubnetIds:
        - !Ref DAXSubnet1
        - !Ref DAXSubnet2
Code language: YAML (yaml)

今回は2つのプライベートサブネットを指定します。

IAMロール

EC2インスタンスやLambda関数等のクライアントがDAXにアクセスすると、DAXは内部的にDyanamoDBに問い合わせを行い、その結果をクライアントに返します。
つまりDAXにDynamoDBにアクセスする権限を与える必要があります。
DAXへの権限付与は、クラスターにIAMロールを関連づけることで行います。

Resources:
  DAXRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - dax.amazonaws.com
      Policies:
        - PolicyName: !Sub "${Prefix}-DAXPolicy"
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - dynamodb:DescribeTable
                  - dynamodb:PutItem
                  - dynamodb:GetItem
                  - dynamodb:UpdateItem
                  - dynamodb:DeleteItem
                  - dynamodb:Query
                  - dynamodb:Scan
                  - dynamodb:BatchGetItem
                  - dynamodb:BatchWriteItem
                  - dynamodb:ConditionCheckItem
                Resource:
                  - !Ref DynamoDBTableArn
Code language: YAML (yaml)

AWS公式ページを参照し、設定を行いました。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.access-control.html

DynamoDBに対する各種権限を与える内容です。

DynamoDB

Resources:
  Table:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: partition_key
          AttributeType: N
        - AttributeName: sort_key
          AttributeType: N
      BillingMode: PROVISIONED
      KeySchema:
        - AttributeName: partition_key
          KeyType: HASH
        - AttributeName: sort_key
          KeyType: RANGE
      ProvisionedThroughput:
        ReadCapacityUnits: !Ref ReadCapacityUnits
        WriteCapacityUnits: !Ref WriteCapacityUnits
      TableClass: STANDARD
      TableName: TryDaxTable
Code language: YAML (yaml)

DAX検証用ということで、以下のAWS公式ページで紹介されているテーブルの構造を再現しました。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.run-application-python.01-create-table.html

「partition_key」という名前の属性をパーティションキー、「sort_key」という名前の属性をソートキーとします。

EC2インスタンス

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref InstanceProfile
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - DeviceIndex: 0
          SubnetId: !Ref InstanceSubnet
          GroupSet:
            - !Ref InstanceSecurityGroup
      UserData: !Base64 |
        #!/bin/bash -xe
        pip3 install amazon-dax-client
        wget http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/samples/TryDax.zip
        unzip TryDax.zip
Code language: YAML (yaml)

DAXにアクセスするために、専用クライアントを使用することができます。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.html

今回は以下のAWS公式を参考にします。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.run-application-python.html

具体的には、ユーザデータを使用してクライアントのインストール、サンプルプログラムのダウンロードを実行します。

ユーザデータを使用してEC2インスタンスを初期化する方法については、以下のページをご確認ください。

https://awstut.com/2021/12/02/ec2-init-4ways

インスタンス用のIAMロールを確認します。

Resources:
  InstanceRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - ec2.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Policies:
        - PolicyName: DynamoDBAndDAXFullAccessPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "dax:*"
                Resource:
                  - !Ref DAXClusterArn
              - Effect: Allow
                Action:
                  - "dynamodb:*"
                Resource:
                  - !Ref DynamoDBTableArn
Code language: YAML (yaml)

以下のAWS公式ページを参考にIAMロールを定義します。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.create-user-policy.html

先述のDAXクラスターおよびDynamoDBテーブル対して、すべてのアクションを実行する権限を与える内容です。

Lambda関数

Resources:
  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Code:
        ZipFile: |
          import amazondax
          import json
          import os

          dax_endpoint_url = os.environ['DAX_ENDPOINT_URL']
          dynamodb_table = os.environ['DYNAMODB_TABLE']
          region = os.environ['REGION']

          def lambda_handler(event, context):
            dax_client = amazondax.AmazonDaxClient(
              endpoint_url=dax_endpoint_url,
              region_name=region
              )

            partion_value = '1'

            result = dax_client.query(
              TableName=dynamodb_table,
              ExpressionAttributeNames={
                '#name0': 'partition_key'
              },
              ExpressionAttributeValues={
                ':value0': {'N': partion_value}
              },
              KeyConditionExpression='#name0 = :value0'
            )
            print(result)

            return {
              'statusCode': 200,
              'body': json.dumps(result, indent=2)
            }
      Environment:
        Variables:
          DAX_ENDPOINT_URL: !Ref DAXClusterDiscoveryEndpointURL
          DYNAMODB_TABLE: !Ref DynamoDBTable
          REGION: !Ref AWS::Region
      FunctionName: !Sub "${Prefix}-function2"
      Handler: !Ref Handler
      Layers:
        - !Ref LambdaLayer
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole2.Arn
      VpcConfig:
        SecurityGroupIds:
          - !Ref FunctionSecurityGroup
        SubnetIds:
          - !Ref FunctionSubnet

  FunctionRole2:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
      Policies:
        - PolicyName: DAXFullAccessPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "dax:*"
                Resource:
                  - !Ref DAXClusterArn
Code language: YAML (yaml)

こちらもPython版のDAXクライアントを使用して、DAXにアクセスします。

DAXクライアントの使用方法については、以下のページを参考に実装しました。

https://pypi.org/project/amazon-dax-client/

実行する内容ですが、パーティションキーが「1」の項目をクエリして取得します。

(参考) Lambdaレイヤー

EC2インスタンスの場合と同様に、Lambda関数でもDAXクライアント(amazon-dax-client)を使用します。
Lambdaレイヤーを作成し、これにDAXクライアントを含めることで、Lambda関数がクライアントモジュールをインポートすることができるようになります。
今回はCloudFormationカスタムリソースを使用することによって、このLambdaレイヤーの作成を自動的に実行します。
詳細については、以下のページをご確認ください。

https://awstut.com/2022/07/18/preparing-lambda-layer-package-with-cfn-custom-resources-python-version

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

https://awstut.com/2021/12/02/cloudformation-nested-stacks

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • DynamoDB:TryDaxTable
  • DAXクラスター:saa-02-009-cluster
  • DAXエンドポイント:dax://saa-02-009-cluster.ryxnym.dax-clusters.ap-northeast-1.amazonaws.com
  • EC2インスタンス:i-098244d885d0d7b13
  • Lambda関数:saa-02-009-function2

AWS Management Consoleから各リソースを確認します。
まずDynamoDBを確認します。

Detail of DynamoDB 1.

テーブルが正常に作成されています。
パーティションキー・ソートキーともに正常に設定されていることがわかります。

DAXを確認します。

Detail of dax 1.

DAXクラスターが正常に作成されています。
クラスター内にノードが2つ作成されていることも確認できます。

Detail of dax 2.
Detail of dax 3.

サブネットグループおよびパラメータグループについても、正常に作成されています。

動作確認

準備が整いましたので、実際に動作を確認します。

EC2インスタンスからDAXにアクセスする

SSMセッションマネージャーを使用して、インスタンスに接続します。

% aws ssm start-session --target i-098244d885d0d7b13
...

sh-4.2$Code language: Bash (bash)

SSMセッションマネージャーの詳細については、以下のページをご確認ください。

https://awstut.com/2021/12/01/ssm-session-manager-linux

ユーザーデータの動作を確認します。

まずDAXクライアントのインストール状況です。

[ssm-user@ip-10-0-1-51 /]$ sudo pip3 list installed
---------------------- -------
amazon-dax-client      2.0.3
antlr4-python3-runtime 4.9.3
botocore               1.29.32
jmespath               1.0.1
pip                    21.3.1
python-dateutil        2.8.2
setuptools             57.0.0
six                    1.16.0
urllib3                1.26.13
websockets             10.1
wheel                  0.36.2
Code language: plaintext (plaintext)

確かにクライアント(amazon-dax-client)がインストールされています。

次にサンプルプログラムのダウンロード状況を確認します。

[ssm-user@ip-10-0-1-51 /]$ ls -l
total 40
drwxr-xr-x   6 root root    60 Dec 19 12:20 TryDax
-rw-r--r--   1 root root 20931 Dec 19 05:03 TryDax.zip
...
Code language: plaintext (plaintext)

確かにZIPファイルがダウンロードされた上で展開されています。

02-write-data.py

以下のページのコードを実行します。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.run-application-python.02-write-data.html

DynamoDBテーブルにサンプルデータを保存する内容です。

以下の通り、コードを一部修正します。

#
#  Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
#  This file is licensed under the Apache License, Version 2.0 (the "License").
#  You may not use this file except in compliance with the License. A copy of
#  the License is located at
#
#  http://aws.amazon.com/apache2.0/
#
#  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
#  CONDITIONS OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the License.
#
#!/usr/bin/env python3
from __future__ import print_function

import os
import amazondax
import botocore.session

#region = os.environ.get('AWS_DEFAULT_REGION', 'us-west-2')
region = os.environ.get('AWS_DEFAULT_REGION', 'ap-northeast-1')

session = botocore.session.get_session()
dynamodb = session.create_client('dynamodb', region_name=region) # low-level client

table_name = "TryDaxTable"

some_data = 'X' * 1000
pk_max = 10
sk_max = 10

for ipk in range(1, pk_max+1):
    for isk in range(1, sk_max+1):
        params = {
            'TableName': table_name,
            'Item': {
                "partition_key": {'N': str(ipk)},
                "sort_key": {'N': str(isk)},
                #"pk": {'N': str(ipk)},
                #"sk": {'N': str(isk)},
                "someData": {'S': some_data}
            }
        }

        dynamodb.put_item(**params)
        print("PutItem ({}, {}) suceeded".format(ipk, isk))
Code language: Python (python)

修正したプログラムを実行します。

[ssm-user@ip-10-0-1-150 python]$ python3 02-write-data.py
PutItem (1, 1) suceeded
PutItem (1, 2) suceeded
PutItem (1, 3) suceeded
PutItem (1, 4) suceeded
PutItem (1, 5) suceeded
PutItem (1, 6) suceeded
PutItem (1, 7) suceeded
PutItem (1, 8) suceeded
PutItem (1, 9) suceeded
PutItem (1, 10) suceeded
...
Code language: Bash (bash)

サンプルデータが保存されました。

DynamoDBテーブル側からも保存状況を確認します。

Detail of DynamoDB 2.

確かにデータが保存されています。

03-getitem-test.py

以下のページのコードを実行します。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.run-application-python.03-getitem-test.html

項目を取得するために、直接DynamoDBにアクセスする場合と、DAXを通じて取得する場合を比較する内容です。

以下の通り、サンプルプログラムを一部修正します。

#
#  Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
#  This file is licensed under the Apache License, Version 2.0 (the "License").
#  You may not use this file except in compliance with the License. A copy of
#  the License is located at
#
#  http://aws.amazon.com/apache2.0/
#
#  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
#  CONDITIONS OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the License.
#
#!/usr/bin/env python
from __future__ import print_function

import os, sys, time
import amazondax
import botocore.session

#region = os.environ.get('AWS_DEFAULT_REGION', 'us-west-2')
region = os.environ.get('AWS_DEFAULT_REGION', 'ap-northeast-1')

session = botocore.session.get_session()
dynamodb = session.create_client('dynamodb', region_name=region) # low-level client

table_name = "TryDaxTable"

if len(sys.argv) > 1:
    endpoint = sys.argv[1]
    dax = amazondax.AmazonDaxClient(session, region_name=region, endpoints=[endpoint])
    client = dax
else:
    client = dynamodb

pk = 10
sk = 10
iterations = 50

start = time.time()
for i in range(iterations):
    for ipk in range(1, pk+1):
        for isk in range(1, sk+1):
            params = {
                'TableName': table_name,
                'Key': {
                    #"pk": {'N': str(ipk)},
                    #"sk": {'N': str(isk)}
                    "partition_key": {'N': str(ipk)},
                    "sort_key": {'N': str(isk)}
                }
            }

            result = client.get_item(**params)
            print('.', end='', file=sys.stdout); sys.stdout.flush()
print()

end = time.time()
print('Total time: {} sec - Avg time: {} sec'.format(end - start, (end-start)/iterations))
Code language: Python (python)

修正したプログラムを実行します。

[ssm-user@ip-10-0-1-150 python]$ python3 03-getitem-test.py
...
Total time: 35.522796869277954 sec - Avg time: 0.7104559373855591 sec


[ssm-user@ip-10-0-1-150 python]$ python3 03-getitem-test.py dax://saa-02-009-cluster.ryxnym.dax-clusters.ap-northeast-1.amazonaws.com
...
Total time: 8.720930099487305 sec - Avg time: 0.1744186019897461 sec
Code language: Bash (bash)

今回の検証においては、DAXを経由した方が4倍程度高速であることがわかります。

04-query-test.py

以下のページのコードを実行します。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.run-application-python.04-query-test.html

クエリを実行するために、直接DynamoDBにアクセスする場合と、DAXを通じて取得する場合を比較する内容です。

以下の通り、サンプルプログラムを一部修正します。

#
#  Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
#  This file is licensed under the Apache License, Version 2.0 (the "License").
#  You may not use this file except in compliance with the License. A copy of
#  the License is located at
#
#  http://aws.amazon.com/apache2.0/
#
#  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
#  CONDITIONS OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the License.
#
#!/usr/bin/env python
from __future__ import print_function

import os, sys, time
import amazondax
import botocore.session

#region = os.environ.get('AWS_DEFAULT_REGION', 'us-west-2')
region = os.environ.get('AWS_DEFAULT_REGION', 'ap-northeast-1')

session = botocore.session.get_session()
dynamodb = session.create_client('dynamodb', region_name=region) # low-level client

table_name = "TryDaxTable"

if len(sys.argv) > 1:
    endpoint = sys.argv[1]
    dax = amazondax.AmazonDaxClient(session, region_name=region, endpoints=[endpoint])
    client = dax
else:
    client = dynamodb

pk = 5
sk1 = 2
sk2 = 9
iterations = 5

params = {
    'TableName': table_name,
    #'KeyConditionExpression': 'pk = :pkval and sk between :skval1 and :skval2',
    'KeyConditionExpression': 'partition_key = :pkval and sort_key between :skval1 and :skval2',
    'ExpressionAttributeValues': {
        ":pkval": {'N': str(pk)},
        ":skval1": {'N': str(sk1)},
        ":skval2": {'N': str(sk2)}
    }
}
start = time.time()
for i in range(iterations):
    result = client.query(**params)

end = time.time()
print('Total time: {} sec - Avg time: {} sec'.format(end - start, (end-start)/iterations))
Code language: Python (python)

修正したプログラムを実行します。

[ssm-user@ip-10-0-1-150 python]$ python3 04-query-test.py
Total time: 0.05969858169555664 sec - Avg time: 0.011939716339111329 sec

[ssm-user@ip-10-0-1-150 python]$ python3 04-query-test.py dax://saa-02-009-cluster.ryxnym.dax-clusters.ap-northeast-1.amazonaws.com
Total time: 0.024791479110717773 sec - Avg time: 0.004958295822143554 sec
Code language: plaintext (plaintext)

今回の検証においては、DAXを経由した方が2.4倍程度高速であることがわかります。

05-scan-test.py

以下のページのコードを実行します。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.client.run-application-python.05-scan-test.html

スキャンを実行するために、直接DynamoDBにアクセスする場合と、DAXを通じて取得する場合を比較する内容です。

以下の通り、サンプルプログラムを一部修正します。

#
#  Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
#  This file is licensed under the Apache License, Version 2.0 (the "License").
#  You may not use this file except in compliance with the License. A copy of
#  the License is located at
#
#  http://aws.amazon.com/apache2.0/
#
#  This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
#  CONDITIONS OF ANY KIND, either express or implied. See the License for the
#  specific language governing permissions and limitations under the License.
#
#!/usr/bin/env python
from __future__ import print_function

import os, sys, time
import amazondax
import botocore.session

#region = os.environ.get('AWS_DEFAULT_REGION', 'us-west-2')
region = os.environ.get('AWS_DEFAULT_REGION', 'ap-northeast-1')

session = botocore.session.get_session()
dynamodb = session.create_client('dynamodb', region_name=region) # low-level client

table_name = "TryDaxTable"

if len(sys.argv) > 1:
    endpoint = sys.argv[1]
    dax = amazondax.AmazonDaxClient(session, region_name=region, endpoints=[endpoint])
    client = dax
else:
    client = dynamodb

iterations = 5

params = {
    'TableName': table_name
}
start = time.time()
for i in range(iterations):
    result = client.scan(**params)

end = time.time()
print('Total time: {} sec - Avg time: {} sec'.format(end - start, (end-start)/iterations))
Code language: Python (python)

修正したプログラムを実行します。

[ssm-user@ip-10-0-1-150 python]$ python3 05-scan-test.py
Total time: 0.1732480525970459 sec - Avg time: 0.03464961051940918 sec

[ssm-user@ip-10-0-1-150 python]$ python3 05-scan-test.py dax://saa-02-009-cluster.ryxnym.dax-clusters.ap-northeast-1.amazonaws.com
Total time: 0.05351376533508301 sec - Avg time: 0.010702753067016601 sec
Code language: Bash (bash)

今回の検証においては、DAXを経由した方が3.2倍程度高速であることがわかります。

Lambda関数

Lambda関数からもDAXにアクセスします。

Detail of Lambda 1.

以下が関数の実行結果です。

Detail of Lambda 2.

関数が正常に実行されました。

CloudWatch Logsで関数の実行ログを確認します。

Detail of Lambda 3.

確かにDAXへのクエリによって、パーティションキーの値が「1」の項目を取得することができました。

まとめ

今回はDAXを作成し、EC2インスタンスおよびLambdaからアクセスする方法を確認しました。