Cloud SpannerのDELETION POLICYによるデータの自動削除
この記事は株式会社Gincoのテックブログとして書いています。
Google Cloud が提供するフルマネージドのリレーショナルデータベースサービスとして「Cloud Spanner」があります。
Cloud Spannerは整合性とスケーリングの両立を実現したデータベースサービスで、高い整合性と大量のデータ処理を両立しなくてはならないシステム開発で効力を発揮します。
合計17種類のブロックチェーンのインフラを提供するGincoでは、ブロックチェーン上のデータを日夜処理し続けるために、Cloud Spannerを活用しています。
本記事では、このCloud Spannerをパンクさせず、いかにスリムに利用するかに焦点を当て、コスト増加の要因となる不要になったデータを削除する方法について紹介します。
Cloud Spannerにはデータを自動削除をする仕組みがあり、テーブルにDELETION POLICYを設定することでこれを行うことができます。
DELETION POLICYとは
有効期限(TTL)を設定し、それを過ぎたデータを自動的に削除してくれる機能で、特徴としては以下のようなものがあります。
- テーブルごとに設定できる
- 負荷の低いタイミングに削除を実行してくれる
詳しくはこちらでご確認ください。
データ容量の課題
データ容量の増加については、ブロックチェーン固有の課題というよりは、Cloud Spannerを使う上で発生する課題になるかと思います。
弊社が現在提供している業務用暗号資産ウォレット「Ginco Enterprise Wallet」では、複数のブロックチェーンに対応し、その取引に関する情報をお客様に提供する上で、大量のブロックチェーン上のデータをSpannerに保存しています。
Spannerの容量の大部分を占めていたのは、ブロックチェーンのブロックやトランザクションのデータで、処理を行った後は、時間経過で参照されなくなり必要に応じてブロックチェーンノードから取得すればいいようなデータになります。
夜間のバッチ処理で削除する処理を実装していましたが、対応する通貨が増えていく中で削除しなければいけないデータが増えていくことで夜間に負荷が集中してしまい、新しい通貨を対応した際にその通貨の削除バッチを追加できないといった状況でした。
spannerのコストは、ノードの数とデータ容量によって決まります。1ノードで保存できる上限が4TBとなっているため、容量が増えるとノード数を増やす必要があり、コストが跳ね上がります。
こうした課題は、長く運用しているシステムや多数のユーザに提供しているシステムにも共通するものでもあります。
DELETION POLICYの設定方法
以下のようなブロックを格納しているテーブルがあるとします。
CREATE TABLE EthereumTestnetBlocks (
BlockHash STRING(66) NOT NULL,
Number INT64 NOT NULL,
GasLimit INT64 NOT NULL,
GasUsed INT64 NOT NULL,
・・・
Timestamp INT64 NOT NULL,
) PRIMARY KEY(BlockHash)
TimestampのカラムにはInt型でUnixtimeが格納されていました。
spanner> select BlockHash, Number, Timestamp from EthereumTestnetBlocks limit 1;
+--------------------------------------------------------------------+---------+------------+
| BlockHash | Number | Timestamp |
+--------------------------------------------------------------------+---------+------------+
| 0x0dc46c8a3d32df076faf1d889559bae10ca3dc6a1e1e3d76cf47528fc80c4eab | 8628828 | 1678428084 |
+--------------------------------------------------------------------+---------+------------+
1 rows in set (4.89 msecs)
ところが、DELETION POLICYはDateTime型のカラムでしか設定することができません。そこで、generated column
を利用することでTimestamp型のカラムを生成しています。
※ generated columnは、他の列の値を使って生成されるカラムで元のカラムのデータが変更されれば、合わせて変更されるものになります。
具体的には、ALTER TABLEによりEXPIRED
カラムを追加して、そのカラムを使ってDELETION POLICYを設定しています。
ALTER TABLE EthereumTestnetBlocks ADD COLUMN EXPIRED timestamp as (TIMESTAMP_SECONDS(Timestamp)) STORED;
ALTER TABLE EthereumTestnetBlocks ADD ROW DELETION POLICY (OLDER_THAN(EXPIRED, INTERVAL 3 DAY));
これで、3日経過したデータが削除されるようになりました。
CREATE TABLE EthereumTestnetBlocks (
BlockHash STRING(66) NOT NULL,
Number INT64 NOT NULL,
GasLimit INT64 NOT NULL,
GasUsed INT64 NOT NULL,
・・・
Timestamp INT64 NOT NULL,
EXPIRED TIMESTAMP AS (TIMESTAMP_SECONDS(Timestamp)) STORED,
) PRIMARY KEY(BlockHash), ROW DELETION POLICY (OLDER_THAN(EXPIRED, INTERVAL 3 DAY));
ここでは、日付の経過のみの条件でしたが、generated columnを使うことにより複雑な条件を設定することもできます。例えばステータスが完了になった場合だけ日付を設定するカラムを生成して、そのカラムを使ってDELETION POLICYを設定することで、完了してから○日経過したデータを削除するようなこともできます。
公式ドキュメントに書いてあるので参考にしてください。
generated columnの注意点
既存のテーブルに、Timestamp型のカラムが存在して、ステータスが完了のもののみ削除する必要があるため、generated columnを設定しようとしたのですがエラーになりました。
以下のような制約が原因でした
- 生成された列、または生成された列によって参照される列では、列オプション allow_commit_timestamp を使用できません。
作成日時 / 更新日時のようなカラムがあると思うのですが、allow_commit_timestamp
が使われている場合、有効期限の用途で使うことができませんでした。
データ量が多いテーブルの注意点
Timestamp型のカラムがなかったため、Unixtimeが入っているカラムを使って有効期限のカラムを生成していますが、カラムを追加する必要があり、データ量の多いテーブルだとそれなりに時間がかかります。
具体的には、Bitcoinのテーブルにカラムを追加しようとしたのですが、1億レコード存在しており、カラム追加にどのくらいの時間がかかるのかわからなかったため、保留になっているものがあります。
まとめ
Cloud Spannerには有効期限を設定して、データを削除する仕組みがあります。しかも自動的に負荷の低いタイミングに少しずつ削除を行なってくれて、運用にもやさしいです。
データを削除することで、ノード数を減らすことができるのであればかなりのコスト削減が見込めると思います。
定期的にデータを削除しないといけない状況は結構あると思いますので、削除バッチを実装する代わりにDELETION POLICYを設定することをおすすめします。
株式会社Gincoではブロックチェーンを学びたい方、ウォレットについて詳しくなりたい方を募集していますので下記リンクから是非ご応募ください。
株式会社Ginco の求人一覧
Discussion