Solanaのスナップショットって何?バリデーターを運用する上で知っておきたいポイント
Solanaの「スナップショット」とは何か? 🧐
ブロックチェーン技術は日々進化しており、その中でもSolanaは高速でスケーラブルなブロックチェーンとして注目を集めています。その高速性とスケーラビリティを支える重要な技術の一つが「スナップショット」です。
この記事では、Solanaのスナップショットについて、技術的な詳細を交えながら分かりやすく解説します。
スナップショットとは? 📸
スナップショットは、Solanaブロックチェーンの特定の時点での状態をキャプチャしたデータです。写真を撮るように、ある瞬間のブロックチェーンの状態を「記録」し、後でその状態を復元したり、分析したりするために使用されます。
Solanaのようなブロックチェーンは、常に新しいトランザクションが追加され、状態が更新されます。ノード(バリデータ)がネットワークに参加する際、ジェネシス(ブロックチェーンの最初の状態)からすべてのトランザクションを検証するのは非現実的です。
そこで、スナップショットを使うことで、最新の状態に素早く同期することが可能になります。
バリデータークライアントが生成するスナップショットの例
現在のベストプラクティスでは、バリデーターは複数のNVMe SSDに特定のディレクトリをマウントさせます。
ただ大きく分けるとledgerとaccountsの2つに分けることが多く、スナップショットはledgerと同居させることが多いです。
以下はそのledgerディレクトリの例です
firedancer@server:/mnt/ledger$ ls -alF
total 6494260
drwxr-xr-x 9 firedancer firedancer 4096 Jan 19 11:25 ./
drwxr-xr-x 5 root root 4096 Jan 19 08:32 ../
drwxr-xr-x 2 firedancer firedancer 20480 Jan 19 11:25 accounts_hash_cache/
drwxr-xr-x 2 firedancer firedancer 565248 Jan 19 11:12 accounts_index/
srw------- 1 firedancer firedancer 0 Jan 19 10:50 admin.rpc=
drwxr-xr-x 2 firedancer firedancer 4096 Jan 19 09:37 banking_trace/
-rw-r--r-- 1 firedancer firedancer 634263 Jan 19 11:25 contact-info.bin
-rw-r--r-- 1 firedancer firedancer 188024 Feb 4 2020 genesis.bin
-rw-r--r-- 1 firedancer firedancer 46041 Jan 19 09:24 genesis.tar.bz2
-rw-r--r-- 1 firedancer firedancer 551213261 Jan 19 11:00 incremental-snapshot-312781563-312809439-8ctFtTd1x5snmfmeSZn2tVy2Wa6SytKZdKEXqzhLLK85.tar.zst
-rw-r--r-- 1 firedancer firedancer 270844404 Jan 19 11:23 incremental-snapshot-312809547-312812417-BpmVUNiFYP6EKkG1BeMwDuRvzWPUsx3UN8qCPcV867Ez.tar.zst
-rw-r--r-- 1 firedancer firedancer 271345207 Jan 19 11:24 incremental-snapshot-312809547-312812540-46os44XeVP4G4nYNZnKq59ZpPpMVpetc9EqirNaHkMG9.tar.zst
-rw-r--r-- 1 firedancer firedancer 274347417 Jan 19 11:25 incremental-snapshot-312809547-312812648-3wzDYnA3zTb4sCHzDSwsoMsF9QcQDYdHFcGE9W2RJTEq.tar.zst
-rw-r--r-- 1 firedancer firedancer 275505012 Jan 19 11:25 incremental-snapshot-312809547-312812765-843nia6SpQSMZjHgFS2dEfuxMh88PsC6W64ekeYa4rov.tar.zst
-rw-r--r-- 1 firedancer firedancer 0 Jan 19 08:50 ledger.lock
drwxr-xr-x 2 firedancer firedancer 4096 Jan 19 11:02 remote/
drwxr-xr-x 2 firedancer firedancer 12288 Jan 19 11:26 rocksdb/
-rw-r--r-- 1 firedancer firedancer 5005328723 Jan 19 11:02 snapshot-312809547-BtuQ2XqPZRFUggX31Xpg3E3ZCyVojW8dRo4xmvYoKG4Y.tar.zst
drwxr-xr-x 3 firedancer firedancer 4096 Jan 19 11:25 snapshots/
drwxr-xr-x 2 firedancer firedancer 4096 Jan 19 09:24 tmp-genesis/
incremental-
で始まるファイルとsnapshot-
で始まるファイルがあると思いますが、これがスナップショットファイルになります。
さらにtmp-snapshot-
というものがある場合、それは作成中のスナップショットを意味します。古いものは削除され、新しいものと置き換わります。
なお、snapshots
という名前のディレクトリがあると思いますが、これは……謎です。
おそらく外部からダウンロードしたスナップショットと、内部で生成された検証不要なスナップショットを区別するためのものと言われています。普通のバリデーターは特に触りません。
誤解を恐れずに言えば、スナップショットというのはほぼ、ある時点の有効なアカウントすべてのスナップショットのことです。
ネイティブトークンであるSOLが含まれるアカウントすべてのスナップショットであり、pubkeyをキーにしたHashMapみたいなものです。今後無限に増え続けると予想されます。
ではスナップショットファイルは全部アカウントの情報のことかといえば全部ではありません。アカウント情報以外に、そのスナップショットのバージョン情報やbank状態と呼ばれる、ネットワークのステーク情報や、特定のスロットでのチェーンの状態などが記録されています。
フルスナップショット vs インクリメンタルスナップショット 🔄
スナップショットには、フルスナップショットとインクリメンタルスナップショットの2種類があります。
フルスナップショット
- 特定のスロットにおけるすべてのアカウントデータを含みます。
- 例:
snapshot-139240745-D17vR2iksG5RoLMfTX7i5NwSsr4VpbybuX1eqzesQfu2.tar.zst
-
約25000スロットごとに作られ、だいたい3時間に一回ぐらい作られています
- 約と書いてあるのは、設定では25000なのですが、保存されるのはぴったり25000スロットではないからです
- 2つのフルスナップショットのベーススロットの差はたいてい25000以上で、AnzaのWill Hickeyも25000ぴったりではないと言及しています。
インクリメンタルスナップショット
- 特定のスロットと前回のスナップショットの間で変更されたアカウントデータのみを含みます。
- 例:
incremental-snapshot-100-200-AvFf9oS8A8U78HdjT9YG2sTTThLHJZmhaMn2g8vkWYnr.tar.zst
- 約100スロットごとに作られていますが、こちらもぴったり100ではなく数スロットの差が常にあります
- 約1分に1度の頻度で生成されます
インクリメンタルスナップショットは、フルスナップショットと組み合わせて使用され、データの更新を可能にします。
逆に言えば、インクリメンタルはフルがないと意味がありません。あくまでインクリメンタルは差分なので。
スナップショットの中身は?
スナップショットはZstandard形式で圧縮されたtarアーカイブです。
典型的には中身は以下の通り。
version
snapshots/
snapshots/status_cache
snapshots/1964
accounts/
..大量のファイル
versionは何かのバージョンのようです。
snapshotsディレクトリの中身は最新のブロックとデータベースの状態に関する情報を含むメタデータファイルが入っています。
accountsディレクトリは、以下のように大量のアカウントファイルと呼ばれるファイルがあります
これは特定のスロットのすべてのアカウントデータを含むファイルで、各ファイルはバイト形式でアカウントのリストとして構成されていますが、Agaveの実装ではアカウントを含むファイルはAppendVecと特に呼ばれています。
ただAnzaの説明ではこの名前はSolana labs時代の古いものらしく、コードベースで「追加(appending)」操作がされなくなっているそうなので、不適切と言われています。
そのためある人はAccountFile
と呼び、別のある人はaccounts vec
と呼んだ方がいいと主張しています。
さて、この大量のファイルは展開されると、個別にメモリにロードされます。
各ファイルのlengthを読み取り、AccountsDB
コードで使用できるAccountFile
形式に整理されます。
バリデーター再起動時には何が行われているのか?📦
バリデーターであればSolanaバリデーターの再起動が定期的に行われていることを知っています。
メインネットはここ1年以上落ちていませんが、テストネットは2-3ヶ月ぐらいに意図的に落としたり、バグによって落ちることがあります。これはニュースにならないので、知らない人も多いでしょう。
その時バリデーターはDiscordに集まって、最後の楽観的確認済みスロット(optimistic confirmed slot)を調査します。これはスーパーマジョリティによって確認された最後のスロットの意味ですが、これがどのタイミングなのかをagave-ledger-tool
というものを使って調べます。
agave-ledger-tool -l ledger latest-optimistic-slots
もし突然のクラスタ停止の場合は、バリデーターたちはagave-ledger-tool
を使って、最終楽観的確認済みスロットまでのデータを持つスナップショットを生成します。
$ agave-ledger-tool -l <LEDGER_PATH> --snapshot-archive-path <SNAPSHOTS_PATH> --incremental-snapshot-archive-path <INCREMENTAL_SNAPSHOTS_PATH> create-snapshot SLOT_X <SNAPSHOTS_PATH> --hard-fork SLOT_X
最終楽観的確認済みスロットが312256121
の場合、以下のような2つのスナップショットができるはずです
snapshot-<BASE_SLOT>-<BASE_SNAPSHOT_HASH>.tar.zst
incremental-snapshot-<BASE_SLOT>-312256121-<SNAPSHOT_HASH>.tar.zst
バリデータークライアントは最も新しいスナップショットを優先的に使うので、これより後のスロットが使われないように、他の無関係なスナップショットは適当なバックアップディレクトリを作って移動させます。
この時点でバリデータークライアント(現在のagave-validator)は停止されているのですが、再起動するとクライアントはローカルにあるスナップショットからアカウントデータを取得します。
内部的にはuntarコマンドでuntarして、読み込んだデータをパースしていきます(だいたい1分半ぐらいかかります)。
その後にAccountsDBとバンク状態を生成します。
// Begin the creation of initial Bank / AccountsDB from deserialized snapshot
[2023-04-19T07:08:19.457996549Z INFO solana_runtime::snapshot_utils] snapshot version: 1.2.0
[2023-04-19T07:08:19.458053497Z INFO solana_runtime::snapshot_utils] snapshot version: 1.2.0
[2023-04-19T07:08:19.458076611Z INFO solana_runtime::snapshot_utils] Loading bank from full snapshot /home/sol/ledger/snapshot/tmp-snapshot-archive-YY2Vb0/snapshots/189242108/189242108 and incremental snapshot Some("/home/sol/ledger/snapshot/tmp-snapshot-archive-c84wHI/snapshots/189262173/189262173")
引用: Solana validator v1.14.17 startup + catchup logs
さて、この時点ではまだスナップショットが信頼できるものかは分かりません。
破損があったり意図的に書き換えられている可能性がないとも言えないので、ブロックの検証をします。Solanaは検証作業をマルチスレッドで実行するのですが、だいたい3分ぐらいかかります。
バリデーターをしているときに、実際にローカルのバリデーターを動かし始めてキャッチアップを始めるまでに謎の時間帯が数分あります。
裏側ではバリデータークライアントが動いてローカルのスナップショットからパースしたりAccountsDBを生成したり検証したりしているわけです。
これが終われば他のバリデーターからshredというデータの断片が流れてきます。これを検証して問題がなければディスクに保存、という流れになります。
あまりに古いスナップショットしかないと、クラスタの最新のスロットにキャッチアップ出来ないということもよくあります。この場合は一度古いスナップショットを消して、他の外部バリデーターからダウンロードするしかありません。
これはshredを受信し解析する速度よりもスナップショットとして受け取って処理した方が遥かに高速なためです。
スナップショットの用途 🛠️
スナップショットは、バリデーター再起動以外にもブロックチェーンの分析にも使われます
agave-ledger-tool
を使えば、例えば、特定の時点でのアカウント残高やネットワークのステーク分布を調査する際に役立ちます。
agave-ledger-tool
は最新のスナップショットファイルを優先的に使うので、古いデータを調査したいときは新しいものを別の場所に移動させておきましょう。
(私はあまり使ったことがないのですが……)
スナップショットの運用あれこれ 🏆
known-validatorからのダウンロードが遅い場合
スナップショットはかつてはダウンロードに長い時間がかかっていました。そこで以前はsnapshot-finderという非公式外部ツールを使うことで、1分ほどで終わらせていました。
最近ではknown-validatorからのダウンロードだけで十分短い時間にスナップショットのダウンロードを終わらせられるので、個人的にsnapshot-finderを使う機会はありません。
ただknown-validatorが遅い場合もあり、その場合はやはり非公式ですが、スナップショットをダウンロードするサイトがあるのでそちらも念の為見ておくといいと思います。
またお金に余裕がある人はセカンダリーサーバー上で無投票バリデーターを立てておき、いざとなったらそちらからダウンロードさせる人もいると思います(この場合はホットスワップするという選択肢もありますが)
スナップショットは消さずにバックアップ
スナップショットは削除しないのが基本です。
不要なスナップショットがある場合、適当なバックアップディレクトリを作って移動させましょう。
まとめ 🎯
Solanaのスナップショットは、ブロックチェーンの状態を効率的に管理し、ノードの同期や再起動を迅速に行うための重要な技術です。フルスナップショットとインクリメンタルスナップショットを組み合わせることで、データの更新や同期が効率的に行えるようになります。また、スナップショットは分析や監査にも活用できる強力なツールです。
Solanaの高速性とスケーラビリティを支えるスナップショット技術は、今後のブロックチェーン開発においても重要な役割を果たすことでしょう。🚀
内容に間違いがあったり、すでに時代遅れになっている可能性もあります!コメント欄で教えて頂けると助かります。
参考記事
Solana Validator Education - Validator Startup Logs
Solana Validator Education - Local Validator State
Informal Guide to Solana Snapshots
What is an exact definition of a snapshot on Solana
A Deep-dive into Solana's AccountsDB
Discussion