🚀

DynamoDB Accelerator(DAX)を使用してみる

2025/01/22に公開

LT

2024年の振り返りをしつつ、2025年に何をしていこうかを記録したいと思います。

2024年の振り返り

2024年は新規プロダクト(広告計測ツール)を開発しながら、フロントエンドに多く触れる機会を得られました。
これまではバックエンドに強いフルスタックエンジニアという立ち位置でしたが、今年はフロント側の技術も学ぶことができ、より広い意味でのフルスタックエンジニアとして成長できたと思っています。

2025年にやっていきたいこと

2025年は、引き続き広告計測ツールの磨き込みを行いながら、さらに新たなプロダクト開発にも挑戦していきます。
技術的には、より高負荷な処理に耐えうるアーキテクチャや、コスト効率の最適化を狙っていきたいと考えています。
DynamoDBを多用しているプロダクトなので、その周辺技術として DynamoDB Accelerator(DAX) を導入し、パフォーマンス改善を図ってみました。
また、プロダクトに活用できる技術を積極的に取り入れていきます。

DynamoDB Accelerator(DAX)とは

さて、本題のDAXについてです。
DAXはDynamoDBの読み取りを数倍から数十倍拡張したキャッシュサービスです。
DAXクラスターがアプリケーションとDynamoDBの間に入り、よく参照されるデータをキャッシュすることで、DynamoDBへのリクエストを減らし、結果的に高速化とコスト削減を同時に実現できます。

ミリ秒からマイクロ秒へと最大 10 倍のパフォーマンス向上を実現します。DAX は、開発者がキャッシュの無効化、データ集計、またはクラスター管理を行う必要なく、DynamoDB テーブルへのインメモリアクセラレーションの追加に必要な作業をすべて担います。DAX は既存の DynamoDB API コールと互換性があるため、アプリケーションロジックを変更する必要はありません。 DynamoDB 同様、プロビジョニングした容量に対してのみのお支払いとなります。スケーリングのパフォーマンスについて心配することなく、顧客向けのアプリケーションの構築に集中できます。(awsの公式からそのまま持ってきました)

プログラムについても、DynamoDBクライアントを置き換えるだけで導入できます。

コストについて

DAXのコスト構造

インスタンスタイプとノードの数、使用時間によって料金が変わります。
下記の例ではインスタンスタイプでdax.r5.large、ノードの数は3です。

DynamoDBのみと比較

DAXのキャッシュがヒットしDynamoDBの読み取り量が減る為、DynamoDBの読み取り料金は減少しますが、DAXのコストが発生するため総合的なコストは増加する傾向にあります。

DAXを使用する

インフラ構築

まず、DAXを構築します。ここではserverless.ymlを用います。

provider:
  name: aws
  runtime: nodejs18.x
  stage: ${opt:stage, 'dev'}
  region: ap-northeast-1
  vpc:
    securityGroupIds:
      - sg-xxxxxxxx  # 適切なセキュリティグループIDを指定
    subnetIds:
      - subnet-xxxxxxxx  # 適切なサブネットIDを指定
      - subnet-yyyyyyyy

resources:
  Resources:
    DAXSubnetGroup:
      Type: AWS::DAX::SubnetGroup
      Properties:
        Description: Subnet group for DAX cluster
        SubnetIds:
          - subnet-xxxxxxxx
          - subnet-yyyyyyyy

    DAXAccessRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service: dax.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: DAXAccessPolicy
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - dynamodb:DescribeTable
                    - dynamodb:Query
                    - dynamodb:GetItem
                    - dynamodb:Scan
                  Resource: "*"

    DAXCluster:
      Type: AWS::DAX::Cluster
      Properties:
        ClusterName: ${self:service}-${self:provider.stage}-dax
        NodeType: dax.r5.large  # インスタンスタイプを選択
        ReplicationFactor: 3    # DAXノードの数
        IamRoleArn: !GetAtt DAXAccessRole.Arn
        SubnetGroupName: !Ref DAXSubnetGroup
        SecurityGroupIds:
          - sg-xxxxxxxx  # LambdaなどのサービスとDAX間のトラフィックを許可するセキュリティグループ
        SSESpecification:
          SSEEnabled: true

アプリケーションの修正

nodejsで実装。
DynamoDBを使用していた場合修正箇所はconst dynamoDB = new AWS.DynamoDB.DocumentClient({ service: dax });となります。envで初期化せずにdaxで初期化する。

const AWS = require('aws-sdk');
const AmazonDaxClient = require('amazon-dax-client');

// 環境変数からDAXエンドポイントを取得
const daxEndpoint = process.env.DAX_ENDPOINT; // 例: "mydaxcluster.abcdef.clustercfg.dax.ap-northeast-1.amazonaws.com"

// DAXクライアントを初期化
const dax = new AmazonDaxClient({ endpoints: [daxEndpoint], region: 'ap-northeast-1' });

// DAXを使用してDynamoDBドキュメントクライアントを作成
const dynamoDB = new AWS.DynamoDB.DocumentClient({ service: dax });

// 例: DAX経由でDynamoDBをクエリ
const params = {
  TableName: 'YourTableName',
  KeyConditionExpression: 'analysis_tenant_id = :tenantId and session_id = :sessionId',
  ExpressionAttributeValues: {
    ':tenantId': 'tenant123',
    ':sessionId': 'session456',
  },
};

dynamoDB.query(params, (err, data) => {
  if (err) {
    console.error('DAXでのクエリ中にエラーが発生しました:', err);
  } else {
    console.log('クエリに成功しました:', data);
  }
});

参照

https://aws.amazon.com/jp/dynamodbaccelerator/

https://aws.amazon.com/jp/blogs/database/how-to-increase-performance-while-reducing-costs-by-using-amazon-dynamodb-accelerator-dax-and-aws-lambda/

Discussion