SJ blog
database
A

信頼度ランク

S 公式ソース確認済み
A 成功実績多数・失敗例少数
B 賛否両論
C 動作未確認・セキュリティリスク高
Z 個人所感

DynamoDB DAX — インメモリキャッシュの仕組みと設計パターン

DynamoDB Accelerator(DAX)のアーキテクチャ、アイテムキャッシュとクエリキャッシュ、TTL設定、DAXが向かないワークロード、ElastiCacheとの使い分けを解説。

一言結論

DAXはSDK変更のみで導入できるDynamoDB専用キャッシュだが、強整合性読み取りには対応していないためDAXと直接DynamoDBアクセスを使い分ける設計が必要であり、キャッシュヒット率が低いワークロードではコスト効果が出ない。

DAX の概要

DynamoDB Accelerator(DAX)はDynamoDB専用のフルマネージドインメモリキャッシュクラスターだ。読み取りレイテンシーをミリ秒からマイクロ秒に削減する。

DAXの特徴:
  → DynamoDBと互換性のあるAPI(SDKを変更するだけ)
  → マイクロ秒の読み取りレイテンシー(通常のDynamoDB: 1〜数ms)
  → 最大10ノードのクラスター(書き込みノード1 + 読み取りノード最大9)
  → VPC内に配置(プライベートアクセスのみ)
  → 自動フェイルオーバー

DAXが効果的なケース:
  ✅ 同じアイテムへの大量の読み取り(ホットキーパターン)
  ✅ ミリ秒未満のレイテンシーが必要
  ✅ 読み取り集中型のワークロード
  ✅ DynamoDBのRCU(読み取りキャパシティユニット)を削減したい

DAX クラスターの設定

# DAXクラスターの作成
aws dax create-cluster \
  --cluster-name my-dax-cluster \
  --node-type dax.r4.large \
  --replication-factor 3 \
  --iam-role-arn arn:aws:iam::123456789012:role/DAXRole \
  --subnet-group my-dax-subnet-group \
  --security-group-ids sg-dax-xxx \
  --parameter-group-name default.dax1.0

# DAXが必要なIAMロールのポリシー
# DynamoDBへのフルアクセス(DAXが代理でアクセスするため)

SDK の変更方法

# 変更前(通常のDynamoDB)
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Users')
response = table.get_item(Key={'userId': 'user-123'})

# 変更後(DAX経由)
import amazondax
import boto3

dax = amazondax.AmazonDaxClient(
    endpoints=['my-dax-cluster.xxx.dax-clusters.ap-northeast-1.amazonaws.com:8111']
)

table = dax.Table('Users')
response = table.get_item(Key={'userId': 'user-123'})  # 同じAPI

DAX のキャッシュの種類

アイテムキャッシュ(Item Cache):
  → GetItem/BatchGetItemの結果をキャッシュ
  → キャッシュキー: テーブル名 + プライマリキー
  → デフォルトTTL: 5分

クエリキャッシュ(Query Cache):
  → Query/Scanの結果をキャッシュ
  → キャッシュキー: クエリパラメータの組み合わせ
  → デフォルトTTL: 5分
  → データが更新されてもクエリ結果は古い可能性がある

書き込みの動作:
  → DAX はライトスルーキャッシュ(DynamoDB + DAX両方に書き込む)
  → 書き込み成功後にキャッシュが更新される
  → PutItem/UpdateItemはDynamoDBに直接書き込みつつDAXキャッシュも更新

DAX が向かないワークロード

DAXが効果的でないケース:
  ❌ 強整合性読み取りが必要(DAXはEventually Consistentのみ)
  ❌ 書き込み集中型ワークロード(書き込みはDAXの恩恵なし)
  ❌ 大量の異なるアイテムへのアクセス(キャッシュヒット率が低い)
  ❌ DynamoDB以外のキャッシュが必要(ElastiCacheを使う)
  
強整合性が必要な場合:
  → DAXを使わず直接DynamoDBにアクセス
  → または strongly_consistent_read=True を指定(DAXをバイパス)

DAX vs ElastiCache

DAX:
  → DynamoDB専用
  → DynamoDBと同じAPIで使える(SDK変更のみ)
  → ライトスルーキャッシュ(自動同期)
  → DynamoDBのRCU削減に特化

ElastiCache(Redis/Memcached):
  → 汎用キャッシュ
  → RDS, DynamoDB, 外部API等のデータをキャッシュ可能
  → カスタムキャッシュロジックが必要
  → 複雑なデータ構造(リスト、ハッシュ等)を扱える
  → セッション管理、レートリミット等にも使用
  
選択基準:
  DynamoDBのみをキャッシュ → DAX
  複数データソースのキャッシュ、複雑なキャッシュロジック → ElastiCache

コストと性能

DAX ノードタイプ(例):
  dax.r4.large: $0.269/時間(東京)
  dax.r4.xlarge: $0.538/時間
  
3ノードクラスター(dax.r4.large)の月額:
  3 × $0.269 × 720 = $581/月
  
DynamoDB RCU 削減によるコスト効果:
  キャッシュヒット率80%の場合:
  月100万RCU × 0.80 = 80万 RCU 削減
  80万 × $0.000125 = $100/月の節約
  
→ 十分に高いキャッシュヒット率が必要

試験頻出ポイント

シナリオ回答
DynamoDBをマイクロ秒レイテンシーで読み取りDAX
DynamoDBのRCUコストを削減DAX
強整合性読み取りのキャッシュDAX不可(Eventually Consistent のみ)
DynamoDB以外のデータもキャッシュElastiCache
DAXのデフォルトTTL5分(変更可能)

まとめ

DAXはDynamoDB専用のインメモリキャッシュで、APIが完全互換のためSDK変更だけで導入できる。強整合性読み取りは対応していないため、強整合性が必要な操作はDAXをバイパスしてDynamoDBに直接アクセスする。