🐤

DynamoDBの個人的便利ツール(CLI)を作った話

2022/05/29に公開

はじめに

私は業務や趣味開発で、DynamoDBを利用することが多いです。特に趣味開発では、オンデマンドモードにしておけば、リクエストが少ない場合ランニングコストがほぼかからないので気軽に立てられます。[1]
使いやすい反面NoSQL特有の制約があります。今回はその制約からくる面倒な作業を単純にするツールddbrewを作成しました。
一応Goで書きましたが、私自身経験がないので、コードは結構ゴリ押しです。。経験者の方からすると、あまり参考にならないと思います。

インストール

READMEを参照ください。Homebrew or Goがあれば導入可能です。

バックアップ

ひたすらScanを繰り返して、jsonl形式のファイルに書き込む機能です

用途とか

DynamoDBは、DyanmoDB自体の機能とAWS Backupを使ったバックアップ方法があります。ただアカウントを跨いだり、ライトにデータを別環境から移したいケースでは不便でした。
またDynamoDBは、スキャンのペイロードサイズ4MBの制約があります。レスポンスに次の開始位置が返却されるので、ループ処理でデータを取得しきるのですが、毎回スクリプトを書くのも面倒なので、テーブル指定をしたら勝手に取得してくれる機能をつけました。

利用方法

ヘルプ

それぞれショートオプションがありますので、タイプが面倒な場合ご活用ください。

$ ddbrew backup --help
Usage: ddbrew backup <tableName>

Backup DynamoDB table.

Arguments:
  <tableName>    Specify table name to backup.

Flags:
  -h, --help            Show context-sensitive help.
  -L, --local=STRING    Specify DynamoDB local endpoint. ex: (http://)localhost:8000
  -v, --version         print the version.

  -f, --file=STRING     Specify the file path to output (default backup_tableName_yyyymmdd-HHMMSS.jsonl).
  -l, --limit=INT       Limit the number of reads per second to the specified number (units are automatically determined as RCUs for provisioned tables and RRUs for on-demand tables).

通常利用

RCU/RRUを気にしない場合は、以下のコマンドで取得できます。デフォルトでは、backup_tableName_yyyyymmdd-HHMMSS.jsonlというファイルで保存されます。--file オプションを利用すれば、指定可能です。
コンソールにリアルタイムでスキャンしたレコード数を表示しています。

$ ddbrew backup <テーブル名>
created backup_<テーブル名>_20220529-174519.jsonl
scaned records: / 6008
backuped

読み込み制限

秒間のRRU/RCUを制限する場合は、以下のコマンドで制限できます。

ddbrew backup <テーブル名> \
  --limit 10

リストア

前述のバックアップで取得したjsonlファイル、もしくは自前で用意したjsonlファイルをインプットにして、データを書き込みます。

用途とか

テストデータの投入や、別アカウントや同一環境の別の名前のテーブルにデータ投入するときに便利だと思っています。

利用方法

ヘルプ

$ ddbrew restore --help
Usage: ddbrew restore --file=STRING <tableName>

Restore DynamoDB table.

Arguments:
  <tableName>    Specifies table name to restore.

Flags:
  -h, --help            Show context-sensitive help.
  -L, --local=STRING    Specify DynamoDB local endpoint. ex: (http://)localhost:8000
  -v, --version         print the version.

  -f, --file=STRING     Specify the jsonline file containing the table data to be restored.
  -d, --dry-run         Simulate WRUs/WCUs to consume.
  -l, --limit=INT       Limit the number of writes per second by the specified number (the unit is automatically determined as RCU for provisioned tables and RRU for on-demand tables).

通常利用

ファイル指定が必須です。コンソールには、書き込み数とjsonlファイルの何%を書き込んだか進捗をリアルタイムで表示しています。

$ ddbrew restore <テーブル名> --file <ファイルパス>
write record: 6000(2%)

DryRun

--dry-runオプションで、どの程度WCU/WRUを消費するするか確認できます。このオプション時にはrestoreは実行されません。

$ ddbrew restore <テーブル名> -f <ファイルパス> --dry-run
Total item size: 35.10 MB
Total to consume: 204626 WRU

オンデマンドモードは、書き込み要求ユニット100 万あたり$1.25なので、7円 [2] 程度だとわかります。どの程度お金がかかるか不安な際に利用します。

書き込み制限

秒間のWRU/WCUを制限する場合は、以下のコマンドで制限できます。

$ ddbrew restore <テーブル名> \
  --file <ファイルパス> \
  --limit 10

開発時jsonlファイルの容量が大きい場合に、書き込み制限をするとキューが伸びてメモリ消費がとんでもないことになりましたが、キューサイズに応じてストリームの読み込みを抑制するようにしました。

取りこぼし対応

オンデマンドモードだと、初速が早すぎて何件か取りこぼすことがありました。取りこぼしたjsonは、別ファイルを生成してそちらに逃がしています。再度restoreコマンドの--fileオプションで生成されたファイルを指定して再投入してください。

$ ddbrew restore <テーブル名> --file <ファイルパス>
write record: 4944(2%), unprocessed record(unprocessed_record_<テーブル名>_20220529-171229.jsonl): 2449
#                       ↑ 未処理レコード数と表示されたファイルに未処理レコードが書き込まれます

# 再投入
$ ddbrew restore <テーブル名> --file ./unprocessed_record_<テーブル名>_20220529-171229.jsonl

削除

前述のバックアップで取得したjsonlファイル、もしくは自前で用意したjsonlファイルをインプットにして、データを削除します。

用途とか

E2Eテストを実装している最中、既存レコードが悪さしているか切り分けるためにデータをクリアしたいときがありました。コンソールからだと、全て削除することはできないためこの機能を作成しました。[3]

利用方法

ヘルプ

基本的リストアとオプションは同じなので、詳細は割愛します。削除もリストア同様に前述したDryRun 書き込み制限 取りこぼし対応 が入っています。

$ ddbrew delete --help
Usage: ddbrew delete --file=STRING <tableName>

Delete DynamoDB table.

Arguments:
  <tableName>    Specifies table name to delete.

Flags:
  -h, --help            Show context-sensitive help.
  -L, --local=STRING    Specify DynamoDB local endpoint. ex: (http://)localhost:8000
  -v, --version         print the version.

  -f, --file=STRING     Specify the jsonline file containing the table data to be delete.
  -d, --dry-run         Simulate WRUs/WCUs to consume.
  -l, --limit=INT       Limit the number of request units if the target table is on-demand, or capacity units if the target table is provisioned.

DynamoDB Local対応

--local <DynamoDB Localエンドポイント>で利用可能です(shortの場合は-Lです)

今後つけたい機能

とりあえず現在ある機能の完成度を高めたいです。E2Eを拡充したいです。他には以下です。上ほど優先度確か高いです。

  • (リストア/削除) 書き込み漏れを減らすため、書き込みのリトライ処理の追加(--limitを指定していないときのみ、--limitを指定すると秒間の書き込み回数を調節する必要があるのでリトライ考慮がむずかしい)
  • (リストア)特定のフィールドを除外して書き込む機能
  • (全体)金額表示
  • (全体)消費RCU/RRU WCU/WRUのリアルタイム表示
  • (全体)消費RCU/RRU WCU/WRUの実績表示
  • (全体)ライブラリ用のインターフェース

さいごに

GoはCLIフレームワークが充実しておりサクサク実装できました。他にも色々はまったことがありますので、そちらに関しては別途記事を書く予定です!

不備がありましたら、GitHubやZennのコメントにFB頂けるとありがたいです。趣味やテストユースで利用を推奨します。プロダクションでご利用の際は十分にテストの上ご利用ください。

脚注
  1. あまり参考にならないかもしれませんが、DynamoDBをバックエンドしたブログを運用しており、月間500/PV程度で大体$0.04くらいです。 ↩︎

  2. 6.5(円) = 204,626(RRU)/1000,000(RRU)*0.25($) * 127(円/ドル) ↩︎

  3. 無料で全て削除する方法としては、テーブル削除して再作成。もしくはTTL属性をつけるという方法がありますが、デメリットや状況によるので手軽とはいえません。 ↩︎

Discussion