はじめに
本記事はAWSのDynamoDBを使った開発で苦しんだ経験をまとめたものです。ちなみにタイトルの元ネタはこれです。
DynamoDBとは
- AWSが提供するNoSQLのデータベース
- フルマネージドで分散データベースの運用とスケーリングに伴う管理作業をまかせることができる
- 高い可用性と耐久性が特徴
RDSとの違い
- 単純なデータの読み書きに強い
- 複雑なデータの更新に弱い
- Lambdaとの相性が良い
苦しんだこと
- 大規模データの書き込み
- バックアップデータのリストア
大規模データの書き込み
はじめに
こういうよくあるサーバーレスな構成を作りました。
ここまではテンプレ(?)
ある日のこと
これに数千件のデータが書き込きこまれることになりました。
これには数個のテーブルへの書き込みや更新が生じます。
結果
残念!DynamoDBへのデータ書き込み途中でタイムアウトが起こりました。Lambdaは予め設定した実行時間を超えるとタイムアウトを起こして502エラーを返します。
とりあえず対策してみる(1)
タイムアウトが起こったということでLambdaの実行時間やメモリを増設してみました。処理時間は1分くらいでした。
しかしここで知ったのですが、API Gatewayはタイムアウト時間が最大30秒に決まっていて、これ以上の拡張ができません。
とりあえず対策してみる(2)
DynamoDBへの書き込み方法について見直してみました。DynamoDBへのデータの書き込みにPutItemを使用していましたが、BatchWriteItemを使うようにしました。
ここまでは良かったのですが、問題は**UpdateItemのためのBatchWrite的なAPIがなかったということです**。結局30秒以内に処理を終えることができませんでした。
最終的に行った対策
最終的にこんな感じの構成になりました。
間にS3が入ることになりました。
ざっくりとした説明
- Lambda1がアップロードされたデータをS3に書き込み
- LambdaトリガーをセットしたS3が、データ書き込み後にLambda2を呼び出す
- Lambda2がDynamoDBへデータを書き込む
これでAPI Gatewayのタイムアウト時間以内にステータスコードを返すことができました。
しかしこの変更でいくつかの問題も生じたのです。まあ苦肉の策という感じでしたね。。。。
バックアップデータのリストア
DynamoDBの自動バックアップ
DynamoDBにはポイントインタイムリカバリ(PIP)を有効化することができます。これを有効化すると、ある特定の日時のDynamoDBのデータの状態を復元することができるのです。
ポイントインタイムリカバリをやってみる
PIPを行うとバックアップテーブルが別のテーブル名で作成されます。
ここまでは良かったのです。
テーブルの移し替えをどうするか
ここでテーブルデータの移し替えを実際に行うのですが、最初に想定していたのは
- バックアップテーブルを作成する
- 元テーブルの名前を変更する
- バップアップテーブルの名前を元テーブルの名前に変更する
なのですが、DynamoDBにはテーブル名を変更するという機能がありませんでした。
結局どうするのか
この問題の解決はできていないのですが、考えた方法は
- 一度削除元テーブルを削除して、バックアップテーブルから元テーブル名のテーブルを作成する
- 元テーブルを削除してバックアップテーブルからのデータを移植するスクリプトを書く(AWS CLIを使う)
どちらもダウンタイムが避けられないのでやりたくはありませんでした。。。
さいごに
今回の失敗で学んだことは、
- DynamoDBで複数テーブルを作ったり、大量のデータ更新をさせるような設計はよろしくない
- PIPの機能は元テーブルへのリストアを公式でサポートはしていない(これについては単純な私の知見不足であればご指摘いただきたいです)
ですね。とりあえず今後の反省ということで。。。