---
title: "ノードフリートを15倍高速に再構築する方法"
description: "信頼性向上の取り組みの多くは目に見えない。Alchemyがノード状態の復旧を並列転送とプライベートネットワーキングで再構築し、ハードウェア障害時にもレイテンシを安定させた方法を紹介する。"
---

# ノードフリートを15倍高速に再構築する方法

<ImageBlock
  src="https://media.alchemy.com/blog/how-we-rebuild-node-fleets-15x-faster-hero.png"
  alt="ノード復旧、15倍高速化"
  width={1024}
  height={480}
  priority
/>

私たちの信頼性に関する取り組みの大部分は、設計上見えないものになっています。RPCリクエストを送信すると、数ミリ秒で応答が返ってきます。そのリクエストを処理したマシンについて考えることはありません。それが本来あるべき姿です。しかし、その1つのリクエストの背後には、複数のリージョンにまたがる多数のチェーンにわたって、休みなく健全性を保ち続けなければならないブロックチェーンノードの集団が存在します。この規模でノード群の健全性を維持することは、データ移動の問題であり、多くの人が想像するよりもはるかに大きな問題です。

この記事は、この問題を解決するために私たちが行った1つの具体的な投資について書いています。それは、社内で構築した高帯域・並列化されたデータ転送システムと、マシン間専用のプライベートネットワークの組み合わせです。これら2つによって、ノードのストレージを従来よりもはるかに短い時間で再構築できるようになりました。これはまず第一に信頼性への投資であり、信頼性こそがハードウェア障害時にもレイテンシを低く、かつ*一貫して*保つものです。これは、私たちのノードインフラの上に顧客が構築する可用性保証を支える、意図的に設計された1つの要素であり、レイテンシを守るための取り組みのすべてではありません。

率直に言っておくべきことがあります。これは通常時に個々のRPCコールを高速化するものではありません。リクエストパス上に存在しないからです。これが実現するのは、マシンが故障したまさにその瞬間、つまりレイテンシが最もリスクにさらされる瞬間に、復旧を速く確実に行うことです。ですから、肝心な場面においては、これは確かに低レイテンシを支えていると言えます。

## 実際に何を復旧しているのか?

これは直接答えておくべき問いです。「復旧」という言葉はいくつかの意味を持ち得るからです。ここで扱っているのは、**ノードの状態**(ノードがリクエストに応答するために必要な、ディスク上のブロックチェーンデータセット)を健全なハードウェアに復元することです。個々の失敗したリクエストや、転送中のデータ、物理ハードウェア自体を復旧することではありません。

これを用いるのは主に次の3つの状況です。

- **ノードが故障または劣化する場合。** ハードウェアまたはディスクが不健全な状態になり、代替機を立ち上げ、チェーンの完全な状態を素早くロードする必要があります。
- **キャパシティを追加する場合。** あるチェーンのトラフィックが増加し、より多くの健全なノードでそれを処理する必要があり、各ノードはトラフィックを受け付ける前に完全なデータセットを必要とします。
- **新しいチェーンやリージョンを立ち上げる場合。** 新しいノードは空の状態から始まり、有用になるためには数テラバイトの状態が必要です。

いずれの場合も、ボトルネックは同じです。大きく、日々増え続けるデータセットを、素早く確実に新しいハードウェアに載せることです。

## なぜブロックチェーンノードの再構築はデータ移動の問題なのか?

ブロックチェーンのフルノードやアーカイブノードは小さなものではありません。チェーンによって、そのディスク上の状態は数百ギガバイトから数テラバイトの規模に及び、毎日増え続けます。上記のいずれかの状況に直面するたびに、その状態を新しいハードウェアに素早く載せる必要があります。

これには2つの遅い方法があります。1つは、ネットワークから同期させ、ノードにピアから履歴をリプレイさせる方法で、大規模なチェーンでは数日かかることがあります。もう1つは、既に稼働している健全なノードから状態をコピーする方法です。コピーはゼロから同期するよりも劇的に速いため、私たちが最適化しているのはこちらの経路です。

問題は、1度に1台ずつ、共有のネットワーク経路を通じて、この規模のために作られていないツールでコピーする場合、数テラバイトのコピーはそれでも遅いということです。

## rsyncとは何か、そしてなぜそれを超えざるを得なくなったのか?

私たちは最初から何か新しいものを構築したわけではありません。長年、マシン間でファイルをコピー・同期するための標準的なUnixツールである`rsync`を使っていました。

**それは何か。** `rsync`は、あるマシンから別のマシンへファイルをコピーするもので、再実行時に賢く動作します。ローリングチェックサムによる差分アルゴリズムを使い、ファイル全体を再コピーするのではなく、変更された部分のみを転送します。実績があり、広く普及しており、その差分転送のアプローチにより差分コピーは低コストです。2台のマシン間でデータセットを同期する用途では、これに勝るものはなかなかありません。

**私たちの環境で何が破綻したか。** `rsync`は2つのホスト間でファイルを同期するために設計されたものであり、時間的制約のもとで新しいハードウェアにテラバイト単位のデータを移すためのものではありませんでした。私たちの規模では、スループットという明確な限界にぶつかりました。単一の`rsync`ストリームはおおむね逐次処理であり、私たちが運用する高速なネットワークとストレージハードウェアを飽和させるには程遠く、利用可能な帯域幅の多くが遊んでしまいます。フリート規模では、この無駄になった容量が積み重なり、ノード1台あたり数時間の再構築時間と実際の運用上の負担につながります。`rsync`が間違っていたわけではありません。私たちがそれの想定していた用途を超えてしまっただけです。そこで私たちは、健全なノードにできるだけ速く巨大なデータセットを移すという1つの仕事のために、最初から設計された転送ツールを構築しました。

## どう実現しているか: 専用プライベートネットワークと並列転送ツール

私たちはこの問題に2つの面から同時に取り組みました。道路と車両です。

### 道路: 専用プライベートネットワーク

私たちは大量のノードデータ転送を、本番トラフィックを処理する経路とは別の、マシン間専用のプライベートネットワークに移しました。

このプライベートネットワーク上でコピーが実行される瞬間、2つのことが変わります。第一に、大量転送は本番リクエストトラフィックと競合しなくなるため、大規模な再構築が顧客向けのレイテンシを危険にさらすことは決してありません。第二に、ノード間で高く予測可能な帯域幅が得られます。これは転送ツールが利用するように設計された、生の容量であり、最大で毎秒数十ギガビットに達します。

### 車両: 専用設計の並列転送ツール

私たちの社内ツールは1つの仕事だけを行います。健全なソースマシンから宛先マシンへ、ノード状態のディレクトリ全体をできるだけ速くプッシュすることです。この設計は、単一の逐次コピーではほぼ遊んでしまう高帯域リンクを飽和させることを中心に組み立てられています。3つのアイデアがこれを実現しています。

- **多数の並列接続。** 単一のストリームの代わりに、転送は多数の並行TCP接続にまたがって同時に実行されるため、実際にプライベートネットワークの帯域幅を埋めることができます。
- **非常に大きなファイルの分割。** 単一の数テラバイト規模の状態ファイルは1つの接続をボトルネックにしてしまうため、設定可能なサイズしきい値を超えるファイルはバイトオフセットによってチャンクに分割され、各チャンクは並行して独自の接続で送信されます。宛先側は各チャンクをファイルの正しいオフセットに直接書き込みます。
- **小さなファイルのバッチ処理と大きいものから順に送ること。** 多数の小さなファイルはまとめてグループ化され、転送ごとのオーバーヘッドを償却します。また、最大のファイルから転送を開始することで、最も時間のかかる転送がすぐに進行中になります。

### オーケストレーション: AnsibleとAWX

高速な転送ツールも、人がコマンドを打たずに多数のマシンにまたがって確実に実行できなければ意味がありません。私たちは再構築をAnsibleでオーケストレーションしています。これは定義されたタスクを多数のサーバーにまたがって実行するものであり、そのジョブとスケジューリングの制御プレーンであるAWXを通じて管理されています。

その成果として、再構築は再現可能で監査可能なジョブになります。対象を選択し、ワークフローを開始すれば、システムがプライベートネットワークを通じて並行して状態を運び、毎回一貫した結果をもたらします。

## 私たちのソリューションはrsyncよりどれだけ速いのか?

私たちのツールは10〜15倍高速です。シングルスレッドの`rsync`はノード状態を毎秒100〜200MBで移動させます。私たちの並列化された転送は毎秒2〜3GBを維持します。

この速度は、肝心な場面、つまり実際の再構築において現れます。ある本番運用では、13ノード(ソース1台、宛先12台)からなるBase Mainnetのフリートを再構築し、実際のデータ転送は約**35分**で完了し、プライベートネットワークのセットアップと解体を含む全体のワークフローは約**1時間27分**で完了しました。**失敗ゼロ、到達不能ノードもゼロ**でした。従来のノード1台ずつのアプローチでは、同種の再構築が数時間に及ぶ苦役となっていました。

## Alchemyでこれが何をもたらすか

これは基盤レイヤーの能力であるため、その恩恵は私たちのノードフリート上で動作するあらゆるプロダクトに及びます。メカニズムは常に同じです(ハードウェア障害が負荷を集中させ、テールレイテンシを押し上げる前に回復する)が、それがプロダクトごとに何を意味するかを見ていきます。

- **Node & RPC API(AlchemyのRPC API):** 劣化したノードが生き残ったノードに過負荷をかける前に交換されるため、ノード障害時もp95/p99の応答時間が安定します。ユーザーにとって遅いリクエストのスパイクが減ります。
- **データ・インデックスAPI(Transfers、Balances、Token、Webhooks):** 復旧が数時間ではなく短い時間で済むため、バックエンドのノードが再構築される際に、消費するデータのギャップや遅延が減ります。より信頼できるデータを、より早く得られます。
- **Rollups & chain services:** 専用チェーンやアプリ固有チェーンのキャパシティ復旧が速くなるため、1つのハードウェア障害がアプリにとって長期にわたる劣化状態につながることはありません。

これらは実質的な*一貫性*の向上です。私たちは、困難な瞬間を短く、稀なものにすることで、あなたの体験を高速に保っています。

## これが、直接目にすることのない人々にとってなぜ重要なのか

ここで、あなたのアプリケーションとの関係に話を戻します。ノードが劣化または故障すると、そのトラフィックは残りの健全なノードに移さなければなりません。代替機の再構築が遅ければ、その負荷は生き残ったノードに長くのしかかります。そして負荷の集中こそが、まさに*テールレイテンシ*、つまり最も遅いリクエストとして表れるp95・p99の応答時間を押し上げる原因です。(この効果に関する古典的な論考は、DeanとBarrosoによる[The Tail at Scale](https://research.google/pubs/the-tail-at-scale/)です。)復旧を高速化すれば、この窓は狭まります。フリートは、劣化があなたの側で遅い応答として実感される前に回復します。

これが、私たちが「障害に備えて計画する」と言うときに意味することです。私たちはマシンが稼働し続けると仮定しません。マシンは故障するものだと仮定し、故障を小さく、復旧を速く保つために投資します。この転送システムと、その背後にあるプライベートネットワークは、そうした投資の1つです。データセンター内のハードウェアの問題が、あなたのアプリにおけるレイテンシの問題に決してならないようにすることが、そのインフラ全体の仕事です。

おそらくあなたはこれらのことに一切気づかないでしょう。それこそが狙いです。

## 大きな視点で見ると: 速さ、そしてストレス下での速さ

健全な日に良いレイテンシの数字を示すのは簡単です。より難しい主張、つまり本番環境で実際に重要になる主張は、物事が壊れたときにも速いままでいられるかどうかです。低レイテンシは定常状態だけの性質ではありません。それは障害の*最中*にシステムがどう振る舞うか、そしてどれだけ速く回復するかという性質でもあります。これは、そもそも私たちが異種で冗長なノードインフラを運用している理由でもあります。

これは私たちがそれを守る方法の一部です。復旧経路への意図的な投資により、あなたが頼りにしている応答時間は、すべてが順調なときだけでなく、午前3時にマシンがダウンし、誰にも気づかれる前に再構築しなければならないときにも維持されます。

これが、私たちが自らに課している基準です。だからこそ、Alchemyのパフォーマンスへの取り組みは、2台のマシン間でテラバイトをどれだけ速く移動できるかというところまで及んでいるのです。

## よくある質問

**これは私のRPCリクエストを速くしますか?**

通常時は速くしません。あなたのリクエストパス上には存在しないからです。しかし、最も重要な瞬間、つまりハードウェアが故障したときには、あなたのレイテンシを守ります。健全なノードを速く再構築することで、負荷の集中があなたのp95/p99を押し上げるのを防ぎ、ストレス下でも最も遅いリクエストが速いままに保たれます。

**具体的に何を復旧するのですか?**

ノードの状態です。ノードがリクエストを処理するために必要な、ディスク上のブロックチェーンデータセットです。これを使って、故障したノードを交換したり、キャパシティを追加したり、新しいノードやリージョンを立ち上げたりします。個々のリクエストや物理ハードウェアを復旧するものではありません。

**なぜrsyncをそのまま使わないのですか?**

`rsync`は2台のマシン間でファイルを同期する用途に優れており、私たちも長年使ってきました。しかし、単一の`rsync`ストリームはおおむね逐次処理であるため、フリート規模では私たちのネットワークとストレージハードウェアを飽和させることができず、ノード1台あたり数時間もの再構築時間の積み重ねにつながります。私たちのツールは、転送を多数の並列接続にまたがって実行し、非常に大きなファイルをそれらに分割することで、専用プライベートネットワークの帯域幅をフルに活用します。

**ノード復旧の高速化はどのようにレイテンシを改善するのですか?**

ノードが故障すると、その負荷は残りの健全なノードに移ります。再構築にかかる時間が長いほど、その集中した負荷はテールレイテンシ、つまりユーザーが最も遅いリクエストとして感じるp95・p99の応答時間を長く押し上げます。復旧を速くすることで、この窓は狭まり、障害が遅い応答として表面化しなくなります。

**rsyncよりどれくらい速いのですか?**

生の転送スループットでおよそ10〜15倍です。シングルスレッドの`rsync`ストリームが毎秒約100〜200MBであるのに対し、プライベートネットワーク上での私たちの並列化された転送は毎秒2〜3GBです。実際には、これによって数時間かかっていたフリート再構築が、13ノードのBase Mainnetフリート全体でデータ転送が約35分で完了し、失敗ゼロとなるものに変わりました。

_このように設計されたインフラの上で構築したいですか? ドキュメントは_ [alchemy.com/docs](https://www.alchemy.com/docs) _をご覧ください。
