今まで、Google App Script + Spreadsheetで運用してきた勤怠管理ツールを、
Firestoreに乗せ換えてみることにしました。
調べたことなどを、まとめておこうと思います。
Firestoreのデータ
Firestoreのデータの持たせ方
Firestoreは、Key-Valueペアで構成されるフィールド、フィールドを複数もつドキュメント、ドキュメントをまとめたコレクションといった感じで構成されます。
また、コレクション-ドキュメント-サブコレクション-ドキュメントといった具合に、階層構造をもつことも出来ます。
今回採用したデータ構造
ユーザごとに日単位でドキュメントを作成し、月単位のサブコレクションで束ねる構造としました。
連続したドキュメントIDは非推奨ですが、更新頻度的に問題なしと判断しました。
見積
費用を見積もってみます。
私のように小規模な使い方であれば、費用の心配は無さそうです。
ストレージサイズ
こちらの考え方に則り、計算します。
無料分として、1GBが提供されていますので、その範囲に収まるかを見ていきます。
-
一人あたり10年分のサイズ
項目 形式 サイズ 一人あたり1年分 一人あたり10年分 コレクション users 6by(=5by+1by) 6by 6by ドキュメント 11桁のユーザID 34by(=6by+12by+16by) 34by 34by コレクション yyyymm形式の年月 7by(=6by+1by) 84by(=7by*12) 840by ドキュメント yyyymmdd形式の年月日 82by(=6by+12by+7by+9by+16by+32by) 30,012by 300,120by フィールド(出てきた時間) フィールド名(start)の日時型 15by(=6by+1by+8by) 5,490by 54,900by フィールド(帰った時間) フィールド名(end)の日時型 13by(=4by+1by+8by) 4,758by 47,580by 合計 53,194by 531,580by -
人数が増えた場合
人数 サイズ(KB) 費用 1人 519KB $0 10人 5,191KB $0 100人 51,912KB $0 1,000人 519,121KB $0 10,000人 5,191,211KB $0.427
ドキュメントの読み取り
1日あたり、読み取り5万回の無料枠がありますので、その範囲に収まるかを見ていきます。
-
一人あたりの回数
- 読み取り ・・・ 31 (出退勤時間の表示。月末が最大値となる。)
-
人数が増えた場合
人数 読み取りドキュメント数 費用(日単位) 費用(月単位) 1人 31ドキュメント $0 $0 10人 310ドキュメント $0 $0 100人 3,100ドキュメント $0 $0 1,000人 31,000ドキュメント $0 $0 10,000人 310,000ドキュメント $0.094 $2.902
ドキュメントの書き込み
1日あたり、書き込み2万回の無料枠がありますので、その範囲に収まるかを見ていきます。
-
一人あたりの回数
- 書き込み ・・・ 3 (出勤時刻の記録+退勤時刻の記録+打ち間違いの修正)
-
人数が増えた場合
人数 書き込みドキュメント数 費用(日単位) 費用(月単位) 1人 3ドキュメント $0 $0 10人 30ドキュメント $0 $0 100人 300ドキュメント $0 $0 1,000人 3,000ドキュメント $0 $0 10,000人 30,000ドキュメント $0.011 $0.335
処理時間の計測
読み取りと書き込みの時間を確認しておきます。
今回の条件では、いずれも、数百ms程度かかる結果となりましたので、
ひとつのトランザクション内でのFirestoreの処理は極力少なくした方が良さそうです。
環境
- コンピューティング : Cloud Function 128MB
- リージョン : us-east4 *Firestoreと同じリージョン
- ランタイム : Python3.7
- ライブラリ : google-cloud-firestore1.8.1
- 読み取り : collection.stream()
- 書き込み : document.set()
読み取り
約200回分の処理を集計しました。
1回の処理で複数のドキュメントを取得し、月末に近づくに連れて取得するドキュメント数が
増えていく特性を持ちますが、特に影響を受けてはいなそうです。
項目 | 値 |
---|---|
50パーセンタイル | 220ms |
90パーセンタイル | 462ms |
99パーセンタイル | 779ms |
最大 | 1,196ms |
書き込み
約400回分の処理を集計しました。
1回の処理で単一のドキュメントを更新します。
項目 | 値 |
---|---|
50パーセンタイル | 365ms |
90パーセンタイル | 765ms |
99パーセンタイル | 1,228ms |
最大 | 1,470ms |
運用
監視
なるべくAlways Freeの無料枠で安心して使えるようにするための通知ポリシーを考えてみます。
-
Firestoreにおける無料枠
Cloud Functionsには、日ごとにリセットされる無料枠があります(時間、分は筆者にて計算)。
今回はこれを基準にして、通知ポリシーを考えています。日単位 時間単位 分単位 ドキュメントの読み取り 50,000回 2,083回 35回 ドキュメントの書き込み 20,000回 833回 14回 ドキュメントの削除 20,000回 833回 14回 -
通知ポリシーの条件
Resorce Type Metric Aggregator Aligner Period Configuration Firestore Instance Document Reads none sum 1minute Any time series violates/is above/35/1min Firestore Instance Document Writes none sum 1minute Any time series violates/is above/14/1min Firestore Instance Document Deletes none sum 1minute Any time series violates/is above/14/1min
バックアップ
GCPのドキュメントには、手動バックアップの記載しかありませんでしたので、
Firebaseのドキュメントを参照し、毎晩バックアップを自動で取得するよう実装しました。
アーキテクチャ
Cloud Schedulerの設定
項目 | 設定値 | 備考 |
---|---|---|
名前 | scheduledFirestoreExport | |
頻度 | 0 5 * * * | 毎朝5時に実行 |
タイムゾーン | 日本標準時(JST) | 〃 |
ターゲット | Pub/Sub | |
トピック | initiateFirestoreExport | 後述のトピックを指定 |
ペイロード | start export |
Cloud Pub/Subの設定
項目 | 設定値 | 備考 |
---|---|---|
トピックID | initiateFirestoreExport |
Cloud Functionsの設定
項目 | 設定値 | 備考 |
---|---|---|
名前 | firestoreExport | |
リージョン | us-east4 | Firestoreと合わせる |
トリガーのタイプ | Cloud Pub/Sub | |
トリガー | initiateFirestoreExport | 前述のトピックを指定 |
割り当てられるメモリ | 128MB | |
関数インスタンスの最大数 | 1 |
Cloud Storageの設定
項目 | 設定値 | 備考 |
---|---|---|
名前 | fs-daily-export | |
ロケーションタイプ | Multi-region | 可用性を向上 |
場所 | us | Firestoreと同一リージョンか、マルチリージョンである必要がある |
ライフサイクル | オブジェクトが更新されてから3日で削除 | 最新世代があれば十分だが余裕をもって |
その他
データの移行
Firestoreには、最初に決めたロケーションから変更できない制約がありますので、
取得したバックアップを別のプロジェクトに移行する手順を確認しておきます。
環境
- 移行元のリージョン : us-east4
- 移行先のリージョン : asia-northeast1
手順
gcloud config set project 移行元のプロジェクト
gsutil cp -r gs://バックアップデータがあるバケット/対象のフォルダ ./.
gcloud config set project 移行先のプロジェクト
gsutil cp -r ./対象のフォルダ gs://バックアップデータを置くバケット/
gcloud beta firestore import ./対象のフォルダ gs://バックアップデータを置くバケット/対象のフォルダ