- 分散システムエンジニアは、多くの場合、現場でのミスによって負った傷を通じて学ぶ
- 新しいエンジニアたちがこうした傷を負わないようにするために、この文章を書いた
分散システムは頻繁に失敗する
- 分散システムは、他のソフトウェアエンジニアリング分野と違って失敗確率が高い。特に部分的な失敗の確率が高い。
- 分散コンピューティングで働いたことのないシステムエンジニアは、「とにかく2つのシステムに書き込みを送ればいい」や「成功するまで書き込みを再試行し続ければいい」といった発想をしがちだ
- ネットワークシステムは単一マシンよりも頻繁に失敗し、その失敗は部分的である可能性が高い
- 片方の書き込みは成功し、もう片方は失敗するかもしれない。では、データの一貫したビューを得るにはどうすればよいのか。このような部分的失敗は推論がはるかに難しい
- スイッチのダウン、ガベージコレクションによるリーダーの「消失」、ソケット書き込みが成功したように見えて実際には失敗している、といった問題が起こりうる。ローカルメモリから読むほうが、いくつかのスイッチ越しに読むよりはるかに信頼できる
- 「失敗を前提に設計」する必要がある
堅牢な分散システムを書くには、より多くのコストがかかる
- 堅牢な分散ソリューションを作るには、単一マシンのソリューションより多くのコストがかかる。
- 仮想マシンやクラウド技術によって分散システムエンジニアリングは安くなってきたが、それでもなお大きなコストが必要だ。
- シミュレーションは有用だが、実際の分散環境で発生する問題をすべて解決できるわけではない。
堅牢なオープンソースの分散システムはまれである
- 多数のマシンを長期間運用するコストは、オープンソースコミュニティにとって負担になる。
- 趣味でオープンソースコードを書く人たちは、分散システムの多くの問題を探究したり解決したりするための資金的余裕に乏しい。
- 一部の問題は企業のエンジニアが解決するが、彼らの優先順位が常に一致するとは限らない。
調整は非常に難しい。可能な限り避けるべきである
- 水平スケーラビリティの核心は独立性にある。マシン間の通信と合意を最小限にしなければならない。
- 2台のマシンが何かについて合意しなければならないたびに、サービス実装はより難しくなる。
- Paxos アルゴリズムの実装は非常に難しい。
問題をメモリに収められるなら、おそらく些細な問題である
- 分散システムエンジニアにとって、単一マシンに限定された問題は簡単だと見なされる。
- データがいくつかのスイッチ先にある場合、それを高速に処理するのはより難しい。
「遅い」は最も難しい問題である
- 「遅い」とは、ユーザーリクエストを処理する複数のシステムのうち、1つ以上が遅いことを意味しうる。
- 部分的失敗はグラフに現れず、問題が明確になるまでは、その解決に必要なリソースを得ることが難しい。
システム全体でバックプレッシャーを実装しなければならない
- バックプレッシャーとは、提供側システムが要求側システムに失敗を通知し、要求側システムがその失敗をどう扱うかという仕組みを指す。
- バックプレッシャーの仕組みがなければ、連鎖的な障害や意図しないメッセージ損失が発生する可能性が高い。
部分的に可用である方法を見つけなければならない
- これは、システムの一部が失敗しても何らかの結果を返せる能力を意味する。
- たとえば検索システムは、一定時間内にすべての文書を検索できなければ、その時点までに集めた結果を返す。
メトリクスは仕事を完了させる唯一の方法である
- メトリクスを公開することは、システムが実際にどう動いているかを理解するための唯一の方法だ。
- ログファイルは有用だが、しばしば嘘をつく。成功ログはたいてい重複しているため、記録されないことが多い。
平均ではなくパーセンタイルを使うべきである
- パーセンタイルは平均より正確で有用だ。平均はしばしば誤った判断につながる。
容量を見積もる方法を学ばなければならない
- 作業をこなすのに必要なマシン数を知ることは重要だ。
- たとえば、ツイートIDをどれだけメモリに保存できるかを計算するような机上計算を頻繁に行うことになる。
機能フラグはインフラをロールアウトする方法である
- 機能フラグは、新機能をシステムにロールアウトする一般的な方法だ。
- 機能フラグを使えば、プロジェクトへの確信を高め、失敗コストを下げられる。
ID空間は賢く選ばなければならない
- システムのID空間は、そのシステムの構造を形作る。
- たとえば、Twitter API のツイートIDは単純な64ビット数値で、他のデータとは結び付いていない。
データローカリティを活用しなければならない
- データ処理やキャッシュを永続ストレージの近くに保つほうが効率的だ。
- ネットワークは、ポインタ参照や
fread(3) よりも多くの障害と遅延を抱える。
キャッシュされたデータを永続ストレージに書き戻すのは良くない
- 多くのシステムでこの問題が起きる。特に分散システムの経験が浅い人たちが設計したシステムでよく見られる。
コンピュータは思っている以上に多くのことができる
- 経験の浅い実務者から、コンピュータの能力について誤った情報が広まっていることが多い。
- 現代のWebサーバーは、数百ミリ秒以内に数千件のリクエストを処理できる。
CAP定理を使ってシステムを批判すべきである
- CAP定理はシステムを構築するために使うものではない。しかし、分散システム設計を批判する際には有用だ。
サービスを抽出すべきである
- ここでいうサービスとは、ストレージシステムより高いレベルのロジックを含む分散システムを意味する。
- サービス抽出は、ライブラリを作るよりも速く、簡単にデプロイできる。
GN⁺のまとめ
- 分散システムエンジニアリングは、高い障害確率と部分的失敗のため、他のソフトウェアエンジニアリング分野とは異なる。
- 堅牢な分散システムを書くにはより多くのコストがかかり、オープンソースコミュニティではまれである。
- 調整、データローカリティ、バックプレッシャー、部分的可用性といった概念を理解し実装することが重要である。
- メトリクスとパーセンタイルの活用、機能フラグ、ID空間の選択などを通じて、システムの効率と安定性を高められる。
- CAP定理を使ってシステムを批判し、必要なときにはサービスを抽出するのがよい。
1件のコメント
Hacker News の意見
CALM(Consistency as Logical Monotonicity)の原則は、CAP より理解しやすく、より根本的な結果である
Exactly-once 配信は不可能であり、at-most-once 配信か at-least-once 配信のどちらかを選ぶ必要がある
良い記事だ。8年前の文章だが、今でも有効な内容が多い
過去の議論へのリンク:
実用的で現実的な説明が良い。"マイクロサービス"のような流行語がない
Lookout で働いていたとき、Jeff Hodges がこのエッセイを紹介した
この記事の著者と一緒に働いた経験がある
2013年以降、多くのことが変わった