雰囲気で分散システム使ってるやついる!?


**？？？：雰囲気で分散システム使ってるやついる!?**
**？？？：いねぇよな！！！！！**

**むっそ：んなわけねぇよ、いるんだよ！！ここによぉ！！**
(終)

# はじめに
なんか分散システムっぽいのは使えてるけど、いまいち詳しいことは知らないってひとが多いと思います。私もです。

別に分散システムの仕組みを知らなくても問題なかったりするものですが、いざシステム障害などが起きると  **これそもそもの仕組み知らんと無力じゃね？** ってなったりします。(無情にもやばいバグが時々起きたりします)

今回は分散システムにわか勢による分散システムを知るのに良さそうなリンクをまとめたり感想を書いていこうかと思います。


# 分散システムを考え始めたきっかけ
## DynamoDB嘘松事件

### 事件前の実装
現在開発しているプロダクトで下記のような処理がありました。
(先人の過去の遺物が残っていてあまり良くないアーキテクチャになってます)

> フロントエンドのUIでhogeアイテムの変更イベントが発生
⇒ A REST APIをたたく(hogeアイテムのステータスを更新する)
⇒ 処理結果取得
⇒ B REST APIをたたく(hogeアイテムの履歴を更新する)
⇒ 処理結果取得
⇒ フロントエンドのUIで結果を通知

ちなみにA REST APIもB REST APIも下記のスクリプトのような感じで、DynamoDBの同じテーブルの同じhogeアイテムを更新しています。

```python:update.py
# DynamoDBからアイテムを取得
unique_id = "hoge"
record = table.get_item(
    Key={ "unique_id": unique_id }
)

# いろいろと処理を実行する
...

# DynamoDBのアイテムを更新
response = table.update({
    "Key": {"unique_id": unique_id},
    "UpdateExpression": update_expr,
    "ExpressionAttributeValues": update_values,
    "ReturnValues": "ALL_NEW",
})

```

そして、事件が起こる...

### DynamoDB嘘松事件発生

> 顧客サポート担当：なんか顧客から「UIで変更操作したのに状態が変わってない」ってバグ報告が出てるんですがわかります？
むっそ：ちょっと実装調べてみますね。
（ログ調査中）
むっそ：うーん、A REST APIとB REST APIの**DynamoDB更新処理結果はどちらも200を返している**から更新処理自体は成功しているはずだよな...
（AWS DynamoDBコンソールで確認中）
むっそ：おいおい、 A REST APIのDynamoDB更新処理はテーブルに反映されてるのに**B REST APIのDynamoDB更新処理はテーブルに反映されてねぇじゃん。DynamoDB嘘松すぎだろ...**

ということで、とりあえずAWSサポートに相談してみた。


### AWSサポートからの返事
AWSサポートから返事が返ってきました。
すこし要約すると下記のようなことを教えてくれました。

<details>
<summary>AWSサポートから返事(要約)</summary>

> DynamoDBは**デフォルトではアベイラビリティゾーンの数箇所を書き込んだ時点で「書き込みOK」という返答をします。**
すべてのアベイラビリティゾーンへの書き込み結果の反映は「そのうち時間が経てば(DynamoDBの場合は1秒以内)結果的に書き込まれる」という考え方です。**これを「結果整合性」と言います。**
読み取り時にはどこのアベイラビリティゾーンから読み取るかはわからないので、前の変更が反映されていないアベイラビリティゾーンからデータが読み込まれた場合、古いデータが読み取れてしまいます。
すべてのアベイラビリティゾーンへの書き込みが完了してから読み込みたい(強力な整合性のある読み込み)場合は**ConsistentRead パラメータを有効にしてください**
とのことでした。
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html

</details>

つまり、デフォルトの結果整合性ではなく、強力な整合性を求めるならば、下記のようにコード修正すれば良さそうです。

```python:update.py
# DynamoDBからアイテムを取得(強力な整合性)
record = table.get_item(
    Key={ "unique_id": unique_id },
    ConsistentRead=True
)
```

しかしながら、A REST APIとB REST APIで**瞬時に2回同じテーブル項目を変更するという設計がそもそも良くない**ので、A REST APIに変更処理を集約するということでなんとか事象は収まりました。


### この件で気づいたこと
* NoSQLをRDBみたいな強力な整合性と思って、テーブルを更新しまくるといずれバグ死する
* そもそもの仕組みを知ってないと、変な実装をする可能性が高くなっていずれバグ死する
* DynamoDBは分散システムだし、時代的にも分散システムがアーキテクチャの基本となっているのでちゃんと勉強したい。エアプ卒業したい

みんなも気を付けてほしい。ほんと。


ということで**この記事では、分散システムを学べそうな良いウェブサイトのリンクをひたすら引用して感想を言いまくって学習したいと思います。参考資料が古くて最新情報じゃないみたいな部分とか、解釈を大幅にミスってるところがあればコメントください...**

そして相変わらず情報の取捨選択が苦手なので文字だらけです。
目次から興味のある内容を選んで、読んでいただければ幸いです。

--------------------------------------------------------


# 分散システムとはなにか
## 分散システムの意味

* **[分散システムとは？](https://www.splunk.com/ja_jp/data-insider/what-are-distributed-systems.html)**

> 分散システムとは、さまざまなコンポーネントがネットワーク上の複数のコンピューター(または他のコンピューティングデバイス)に分散しているコンピューティング環境のことです。
分散されたデバイスで作業を分担し、調整して行うため、1台のデバイスで行うよりも効率よくタスクを完了させることができます。

⇒複数のコンピューターが協調して作業を行ってるシステムですよーってことなんだろう。
分散システムを勉強していると **「リーダー選出」** やら **「分散合意」** みたいな単語が出てくるので、コンピューターサイエンスというより **社会科学(政治/経済/経営)** みたいやなって思いました。

**なんかうまく擬人化して理解すると面白いのかもしれない。**


* **[詳説 データベース ―ストレージエンジンと分散データシステムの仕組み(本)](https://www.amazon.co.jp/dp/4873119545/ref=cm_sw_em_r_mt_dp_PCE5VNTR38NEPM6D7HV4)**

⇒もっと分散システムを体系的に理解したいのであれば、この本の**第二部:分散システム**の部分を読むと良さそうです。

全体的に内容が難しく文章説明が多いので、コードで理解したい人とか図で理解したい人であれば、ネット上に落ちてるわかりやすい資料を見つつ、この本を勉強すると良さげです。
(ちなみに私は全然読み切れてないです、不勉強ですいませぬ)


* **[データ指向アプリケーションデザイン(本)](https://www.oreilly.co.jp/books/9784873118703/)**

⇒この本も結構良書だといわれている本です。
本屋でチラ見した程度ですが、すごく体系的にまとまっていそうでした。(本が分厚すぎて買ってないですが)

分散システムの沼に本格的にはまりたい人には良い本かと思います。


## 分散システムの例(NoSQL/NewSQL)

* **[【第14回】NoSQL(1)-基礎-CAP定理を元にしたデータベースの分類とデータ特性](https://debugroom.github.io/mynavi-doc-draft/cloud_native/aws-nosql-1-1.html)**

⇒ グラフなどがまとまっていて良い資料。
最近だといくつかのデータベースサーバーをクラスターにして分散システムを作っているNoSQLが流行していますね。

すべてのデータベースを以下のCAP定理に基づいて分類したときに、 **原則論として２つの特性を重視すると残りの1つが失われるらしい。** 俗にいう[銀の弾丸などない](https://ja.wikipedia.org/wiki/%E9%8A%80%E3%81%AE%E5%BC%BE%E3%81%AA%E3%81%A9%E3%81%AA%E3%81%84)ってやつですね。

<details>
<summary>CAP定理とデータベース分類</summary>

> **CAP定理**
> ・一貫性(**C**onsistency)：
あるデータに対する読み取りは、どのノードにおいても、必ずそのデータの最も新しい書き込みの結果を返すか、エラーを返す
・可用性(**A**vailability)：
システムを構成するノードに障害が発生していたとしても、常に読み込みと書き込みが可能である。
・分断耐性(**P**artition tolerance)：
システムを構成するノード間の通信が一時的に分断されても、機能が継続される。

どの2つを採用しているかでデータベースを分類している。
> ・CA型データベース：RDB
・CP型データベース：Apache HBase、MongoDB、Redis
・AP型データベース：Amazon DynamoDB、Apache Cassandra

</details>


嘘松事件が起こったAmazon DynamoDBは分類としてはAP型データベースなので、一貫性(Consistency)を捨てていたということですね。(強力な整合性のオプションはありますが)

ただ、なんか**この分類自体がしっくりこないなぁって感じが否めないです。**

ネットワークが分断されてしまったら結局全体の一貫性って取れなくない？とか
Master/Slave構成でMasterが死んだらちょっと可用性損なわれない？とか
障害の種類によって前提が崩れそうだなぁ、みたいな雑念が入り込んできます。

という感じでもやもやしてたら、こんな記事がありました。

https://www.publickey1.jp/blog/13/capcap32.html

記事によると、データベースサーバー同士のネットワーク分断が発生した場合に
1.処理を中断して可用性を犠牲にする。
2.処理を進めて一貫性を犠牲にする。

どちらかを選択しなければならない場合があって、それは時と場合によるっていう感じらしいです。**単純に3つの中の2つしか採用できないという話ではない**というのがいまの見解っぽいです。

* **[2020年現在のNewSQLについて](https://qiita.com/tzkoba/items/5316c6eac66510233115)**

⇒私の理解はNoSQLで止まってしまっていますが、NewSQLというのがあるらしい。
NewSQLは新しい形のSQLデータベースで、スケーラブル・分散アーキテクチャなど、過去のRDBMSにはない特徴を持つようなので、ちゃんと最新動向を追わないとなぁと思いました。


# 分散システムの問題
## 分散システムの誤謬

* **[分散コンピューティングの落とし穴](https://ja.wikipedia.org/wiki/%E5%88%86%E6%95%A3%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E8%90%BD%E3%81%A8%E3%81%97%E7%A9%B4)**

⇒Fallacies of Distributed Computingという英語から日本に輸入されたようで、日本語では「分散コンピューティングの誤謬(ごびゅう)」「分散コンピューティングの落とし穴」みたいな訳らしい。その誤謬は以下の８つです。

<details>
<summary>分散コンピューティングの誤謬</summary>

1. ネットワークは信頼できる。
2. レイテンシはゼロである。
3. 帯域幅は無限である。
4. ネットワークはセキュアである。
5. ネットワーク構成は変化せず一定である。
6. 管理者は1人である。
7. トランスポートコストはゼロである。
8. ネットワークは均質である。

</details>

分散システムは、複数のコンピューターが協調してクラスターとして動いているので、クラスターの中には**年代物のご老人サーバー**や**CPUバリバリの新進気鋭若手サーバー**などもいて、そりゃレイテンシなども変わるだろうなと思いました。


* **[Navigating the 8 fallacies of distributed computing](https://ably.com/blog/8-fallacies-of-distributed-computing)**

⇒英語で書かれてて読むの大変ですが、分散システムを構築するときにどのように分散コンピューティングの落とし穴を回避するかというのが書いてあります。

ネットワークの冗長構成でネットワークの耐障害性を高めたり、負荷に応じてオートスケールさせたりなど書かれています。これってAWSなどの**クラウドベンダーが推奨しているアーキテクチャに基づいて構築していれば割と回避できるんじゃね**と思ったりします。


## ビザンチン将軍問題

* **[ビザンチン将軍問題](https://ja.wikipedia.org/wiki/%E3%83%93%E3%82%B6%E3%83%B3%E3%83%81%E3%83%B3%E5%B0%86%E8%BB%8D%E5%95%8F%E9%A1%8C)**

> ビザンチン将軍問題とは、相互に通信しあう何らかのオブジェクト群において、通信および個々のオブジェクトが故障または故意によって偽の情報を伝達する可能性がある場合に、全体として正しい合意を形成できるかを問う問題である。

> 東ローマ帝国（ビザンティン帝国、ビザンチン帝国）の将軍たちがそれぞれ軍団を率いて、ひとつの都市を包囲している状況で発生する。将軍たちは、都市攻撃計画について合意したいと考えている。最も単純な形では、将軍たちは、攻撃するか撤退するかだけを合意決定する。
一部の将軍たちは攻撃したいと言うだろうし、他は撤退を望むかもしれない。重要な点は、将軍たちはひとつの結論で合意しなければならないということである。つまり、一部の将軍だけで攻撃を仕掛けても敗北することは明らかで、全員一致で攻撃か撤退かを決めなければならないのである。また、将軍たちは、それぞれ離れた場所に各軍団を配置しており、メッセンジャーを相互に送ることで合意を目指す。
問題を複雑にさせているのは、一部の将軍たちが反逆者であって、時折最適でない戦略に票を投じたりして混乱させることである。

⇒**地理的に離れているサーバーたちと合意することの難しさについて、擬人化してるたとえ話ですね。**

戦いの前に事前に合意しとけよ
リーダーの合図で攻撃か撤退か決めてまえよ
なんで東ローマ帝国なんだよ

みたいな各種ツッコミはあるかもしれないが、こういう分散システムネタがあるんだなということで留めておきます。


## スプリットブレイン問題
* **[スプリットブレインシンドローム](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%97%E3%83%AA%E3%83%83%E3%83%88%E3%83%96%E3%83%AC%E3%82%A4%E3%83%B3%E3%82%B7%E3%83%B3%E3%83%89%E3%83%AD%E3%83%BC%E3%83%A0)**

> スプリットブレインシンドローム（split-brain syndrome）またはネットワークパーティション問題とは、複数のコンピュータ（ノード）を相互接続して1台のサーバのように動作させるシステム（密結合クラスター）において、ハードウェアやインターコネクトの障害によりシステムが分断され、1つのサービス(仮想IPを含む)がクラスタ内の複数のノード群で同時に起動してしまい、サービス供給が停止してしまう状況のこと。

⇒この単語通りに受け取ると、
右脳さんと左脳さんが分離してしまって、右脳さんと左脳さんが **「この体を動かすためにお互いコミュニケーションしてたのに俺らどうすればええねん、だれが指揮すんねん」** みたいになってる状態ということです。

このスプリットブレイン問題が発生すると、**「マスターは俺じゃい！！」** みたいな感じでマスターが乱立して複数のマスターでデータベースの書き込み競合が起こって半端ない状態になったりでやばくなる感じです。


* **[クラスタに3ノード必要な理由](https://qiita.com/ntoreg/items/ec6f1eca87ba5c5c0399)**

⇒例えば3台のサーバークラスターでネットワーク分断が発生したときに、1vs2のように分断されれば少数派側はマスターになることをあきらめるので、スプリットブレイン問題は起こらずに済むという感じのようです。

ちゃんと多数決が成立するようにクラスターのサーバー数を奇数にしたほうが良いんですね。
ちょっと政治学みが出てきて面白いですね。サーバー議会ですね。


## その他分散システムの課題

* **[本当は恐ろしい分散システムの話](https://www.slideshare.net/kumagi/ss-81368169)**

⇒これは**分散システムを知るうえで読んでおくべきスライドだ**と思いました。話の構成うますぎるし、ギャグセンスが高い。ハッカーの悪知恵がいかんなく試されていて、こういうネタ大好きです。

以下は心に残ったスライド番号と感想を書いています。

<details>
<summary>スライド番号と感想</summary>

P10 - P17 ネットワーク分断に耐えると主張しているredisとそれを検証して否定するJepsen Testの闘いが面白すぎ。

P49 障害の種類によってはACIDすら守れてないデータベースがあるということが驚き。RDBMS=ACIDみたいな教科書で得た知識はちゃんとアップデートしていかないとならんな。

P58 Netflixは本番環境で異常系も対応できるか確かめるために、システムのプロセスやCPU、仮想マシンをランダムに止めてちゃんと動作するか確認(カオスエンジニアリング)しているらしいが、強いエンジニアがたくさんいるからこそできる所業だなぁと思いました。


</details>



* **[分散処理システムの検証をサービスとして提供するJepsenに注目](https://thinkit.co.jp/article/17532)**

⇒この記事に登場する動画が手書き資料ばかり出てきて「斬新やなぁ」って思ったのは置いといて、ちゃんと正常性がなにかを明確化して、それをテストし抜くことの重要性を感じた。

下記のJepsen Test分析結果は大量すぎて読めてないですが、使用しているデータベースがビジネスで求める分散システムのレベルを満たせているのか？というのは深いレベルで調査しなきゃなぁと思いました。

https://jepsen.io/analyses



* **[分散システムの課題(Amazon Builders' Library)](https://aws.amazon.com/jp/builders-library/challenges-with-distributed-systems/)**

⇒Amazon Builders' LibraryというAWSのドキュメント群のなかの一つが「分散システムの課題」という記事です。**AWSのこれまでの分散システム構築経験に基づいた内容**になっていて全体的に勉強になります。

分散システムはネットワーク上でサーバー同士が頻繁に意思疎通する必要があるので、意図しないネットワークエラーとかサーバーの一つが壊れたとか、プロセスが死んだみたいなものに対処しなきゃならんわけですね。
 **「分散システムはめちゃくちゃ大変なんだぞぉ」** というAWS側の想いが伝わってきます。



# 分散システムの問題への解決策
## 分散合意と周辺用語

* **[Raft Understandable Distributed Consensus](http://thesecretlivesofdata.com/raft/)**

⇒分散合意アルゴリズムRaftの説明アニメーションになっていますが、**分散システムで出てくる分散合意やらリーダー選出の流れをぱっと理解するのにすごく良いサイトになっています。**

まず最初にこのアニメーションをポチポチしながら見ることで、全体像を理解するのが結構オススメです。(英語読むのはつらいけど)


* **[分散システムについて語らせてくれ](https://www.slideshare.net/kumagi/ss-78765920)**

⇒**kumagiさんという方がslide share/Qiitaなどでめっちゃ分散システムについて書いてくれているので、知の高速道路ができてる感がある。非常にありがたい。**

分散合意アルゴリズム周辺の単語が難しいので用語を理解する必要があり、この資料は比較的わかりやすく用語説明などを書いてくれています。
以下は心に残ったスライド番号と感想を書いています。

<details>
<summary>スライド番号と感想</summary>

P5 ディスクIO/ネットワークは遅いというのを分かってないで実装する人は結構見かけるし、分散システムを理解する中でも、その観点を忘れずにいたいと思いました。

P15 サーバーが複数台あるときにどの程度を故障とするか、という故障モデルの話。

素直に**動かなくなって故障してくれているほうがエラーハンドリングしやすくて、中途半端に故障と正常を繰り返してたり、正常みたいな顔して実は虚偽報告してました、みたいなほうがエラーハンドリングが難しい**んやなぁと思いました。

* 故障レベル(私の理解)

> 1.故障なし：エラーハンドリングはしんどくない
2.Fail Stop：クラスターのうちどこかのサーバーが壊れていて、クラスター全体で故障だと認知されている状態。この状態へのエラーハンドリングはちょっとしんどい
3.Crash Recovery：サーバーは壊れてるかもしれないし復活するかもしれないという状態。この状態へのエラーハンドリングはかなりしんどい
4.ビザンチン障害：お互いの疎通確認はできているものの、虚偽報告の可能性がある状態。この状態へのエラーハンドリングはめっっっちゃしんどい

P19 合意問題ができることでほかの問題も解けるようになるらしい。

合意問題が解ければ
⇒ リーダー選出が解ける
⇒ アトミックブロードキャストが解ける
⇒ State Machine Replicationが解ける

P22 Paxos単体だと合意しかできないんですね。Raftと同列に見ていたがそれは勘違いでした。PaxosとMulti Paxosの両方を見ていく必要がありそう。

P24 - P32 2相コミットは障害レベル：1.故障なしのときにしか機能しないらしい。
だからこの資料全体で2相コミットはやめてくれって主張しているのか。

P44 RaftとPaxosを比べることでにRaftがいかにシンプルかが分かりますね。複雑な問題をシンプルに解くというのが、プログラマーとしての腕の見せ所だなぁと思ったりしました。

P45 良いですね、毒舌を最後にかましてくるの大好きです。

</details>


## 分散合意アルゴリズム Raft

* **[分散合意アルゴリズム Raft を理解する](https://qiita.com/torao@github/items/5e2c0b7b0ea59b475cce)**

⇒論文をかなりかみ砕いて文章化していてすごい助かります。難しくて分からない部分はあったりしますが、下記でリンクを貼っているslide shareの資料やRaftのRust実装コードを読んでみたり、用語をググってみたりすることで、なんとなく理解できてくるのかなぁと思います。
(まぁ全部を理解するのは難しい)


* **[Raft slide share](https://www.slideshare.net/pfi/raft-36155398)**

⇒処理工程が丁寧に記述されているのでわかりやすいと思います。分散合意アルゴリズム自体、あまり親しみのないアルゴリズムなので説明を丁寧にしていただけるだけありがたいです。


* **[Rust初心者がRustで全文検索サーバを作ってみた](https://qiita.com/mosuka/items/3517ef4a1eb07fa2661f#raft-consensus-algorithm)**

⇒Raftアルゴリズムを組み込むのに苦労したという話がありました。

> RaftのライブラリもPingCAPからraft-rsが提供されているのでこちらを利用します。
実際に組み込み作業を始めますが、このライブラリの使いか方がとても難しかったです。Paulさんも一度チャレンジしたようですが、「使い方がよくわからなかった。完全に失敗したよ」と言っていました。

Githubにある実装も見てみましたが、ライブラリを組み込むのにすごく苦労されているなぁという感じはしました。(読み切れずに力尽きる)
RaftアルゴリズムをRustで組み込みたいときにすごく参考になると思います。

https://github.com/mosuka/bayard/tree/master/bayard-server/src


* **[raft-rs(RaftのRust実装)](https://github.com/tikv/raft-rs)**

⇒RaftのRust実装があったのでちらっと見てみました。

以下のraft.rsで、MessageType::MsgHeartbeatやMessageType::MsgRequestVoteなどのメッセージ処理をしていくなかでbecome_follower関数やらbecome_leader関数やらを呼んで条件分岐していそう。
なんだか**サーバーが選挙に立候補したり投票してるの面白いです。**

ミドルウェア系の実装はあまり親しくないのでちゃんと読んでみたいです。興味がある方はぜひ実装を追ってみて下さい。

https://github.com/tikv/raft-rs/blob/master/src/raft.rs


## 分散合意アルゴリズム Paxos

* **[今度こそ絶対あなたに理解させるPaxos](https://qiita.com/kumagi/items/535c9b7a761d2ed52bc0)**

⇒Pythonコードで説明してくれているのでコードでも理解しやすいです。また以下のような面白い毒舌があるので読んでて楽しいですね。

> Paxosアルゴリズムとは「ただ一つの覆らない値を選択する」アルゴリズムであり、誤解を恐れずに言うとこれ単品ではロクな使い道がない。

Paxosで合意はできるけれど、それ単体ではリーダー選出、アトミックブロードキャスト、State Machine ReplicationはできないからPaxosを拡張したMulti-Paxosなどに頼る必要があるということですね。


* **[Paxos slide share](https://www.slideshare.net/pfi/paxos-13615514)**

⇒[Raft slide share](https://www.slideshare.net/pfi/raft-36155398)と同様に、処理工程が丁寧に記述されているのでわかりやすいと思います。Proposer、Accepter、Learnerの話、学習するための参考文献の話も盛り込まれているので良い資料です。


## 分散合意アルゴリズム PBFT(Practical Byzantine Fault Tolerance)

* **[コンソーシアム型ブロックチェーンで使用できる合意形成アルゴリズム「PBFT」](https://gaiax-blockchain.com/pbft)**

⇒Raft/Paxosでは障害レベル：3.Crash Recoveryまでは対処可能ですが、4.ビザンチン障害には対処できないようです。しかし**PBFT(Practical Byzantine Fault Tolerance)というアルゴリズムであればビザンチン障害まで対応可能になるようです。**

この記事の内容もわかりやすいですし、記事内リンクに**PoW(Proof of Work)などのブロックチェーン関連技術についても説明してくれてとってもありがたいです。**


* **[今ビットコインのブロックチェーンを学ぶ意義とは？Pythonで作ってみたい人のための解説書から紹介](https://codezine.jp/article/detail/11801)**

⇒集中システムと分散システムの説明やブロックチェーンの歴史などが書かれていて良さそうな記事です。**単純に分散システムのことだけ調べようと思っていたのに、ブロックチェーンにまでたどり着いてしまって、点と点がつながって意図しないエクスタシーを感じています。**


## カオスエンジニアリング
* **[カオスエンジニアリングの原則](https://principlesofchaos.org/ja/)**

⇒**カオスエンジニアリングとは分散システムの障害対策/テスト手法。**
構築している分散システムでカオスエンジニアリングしたくなったらこの原則を考慮して設計していこうと思いました。

カオスエンジニアリングするのが多分品質保証としては重要ですけど、開発リソースの余裕がない中でやっても、つらいだろうなぁと思います。うまいバランスでテストしていきたいです。


* **[カオスエンジニアリングで本当にカオスにならないための進め方をグラレコで解説](https://aws.amazon.com/jp/builders-flash/202110/awsgeek-fault-injection-simulator/?awsf.filter-name=*all)**

⇒この記事、絵が面白くて読みやすい。AWS Fault Injection Simulatorっていうのがあるのを知らなかった。AWSでカオスエンジニアリングしてみたくなったら使ってみようと思いました。


* **[Chaos Engineering(oreilly)](https://www.oreilly.co.jp/books/9784873119885/)**

⇒目次から **「たぶん読むの大変なやつだ」** と察してしまいますが、もっと深く体系的にカオスエンジニアリングしたくなったら読んでみたいと思いました。


* **[カオスエンジニアリングの過去と今(前編)](https://zenn.dev/hodagi/articles/3ce6ccdb00538c)**

⇒Netflixの技術史とともにカオスエンジニアリングを語っているので面白い記事だと思いました。本番環境でカオスエンジニアリングしなくても、**本番環境前のステージング環境とかでやれば？** という視点については、**「それが現実的だよなぁ」** って思います。
本番環境でのバグを頻繁に起こされたらヒヤヒヤして眠れなくなりそう



# 実際のサービスの分散システムを見てみる
## AWS DynamoDB

* **[Amazon がリーダーを選ぶ方法](https://aws.amazon.com/jp/builders-library/leader-election-in-distributed-systems/#How_Amazon_elects_a_leader)**

⇒[**リース**](https://en.wikipedia.org/wiki/Lease_(computer_science))という方法を採用することで、Amazonはリーダー選出をしているみたいです。

> リーダーを選出するには、Paxos のようなアルゴリズムから、Apache ZooKeeper のようなソフトウェア、カスタムハードウェア、リースにいたるまで、さまざまな方法があります。リースは、Amazon で最も広く使用されているリーダー選挙メカニズムです。リースは理解して実装するのが比較的簡単で、組み込みの耐障害性を提供します。

資源を排他制御するときに使われる**従来のリソースロックだとロックしているクライアントプロセスによって明示的に解放されるまでリソースの制御権利を付与してしまう。**

しかし**リースだと貸出期間を設けてクライアントプロセスに貸し出して、貸出期間が経過したらクライアントプロセスがどういう状態であろうと、次の人にリソースの制御権利を渡すって感じ**なのかな。多分


* **[How to do distributed locking](https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html)**

⇒RedisのRedlockアルゴリズムの分散ロック方法に警鐘を鳴らしてる記事だと思いますが、**分散ロックの難しさ、リースという概念を理解する手助け**になりそうです。
英語ですが読む価値はすごくあると思います。


* **[Amazon DynamoDB Lock Client](https://github.com/awslabs/amazon-dynamodb-lock-client)**

⇒Amazon DynamoDB Lock Clientは、DynamoDB向けに構築された汎用分散ロックライブラリのようです。Javaで書かれてますが、リース期間中にリソースへと読み書きしてる雰囲気のコードが読み取れます。興味があればコードも読んでみてください。


## Elasticsearch

* **[Elasticsearch as a Distributed System](https://www.slideshare.net/snuffkin/elasticsearch-as-a-distributed-system)**

⇒ElasticsearchのNodeの役割、検索/インデックス更新の流れ、障害検出、スプリットブレイン問題解消メカニズムなどが図で書かれていてすごく理解しやすいです。分散システムとしてElasticsearchを理解したいときにまず読むべき資料かと思いました。


* **[新世代Elasticsearchクラスターコーディネーション](https://www.elastic.co/jp/blog/a-new-era-for-cluster-coordination-in-elasticsearch)**

⇒Elasticsearch version 7だと新たな分散合意システムを導入しているようです。純粋なRaftアルゴリズムなどのプラグインは使わずに、いろんな分散合意アルゴリズムの良さそうなところを組み合わせてる感じなんですね。(得体のしれないものになってないかすこし心配ですが)

> Paxos、Raft、Zab、Viewstamped Replication（VR）などの分散合意アルゴリズムのファミリーに精通していれば、中核となる安全モジュールについてもよく分かります。これは単一の書き換え可能なレジスタをモデル化し、Paxosの投票、Raftのターム、VRのビューに類似したマスター用語の概念を使用します。


* **[Elasticsearch Distributed Consistency Principles Analysis (1) - Node](https://www.alibabacloud.com/blog/594358)**

⇒初めてアリババクラウドのブログを読んだかもしれん。Elasticsearchのソースコードを随所に取り上げつつリーダー選出の仕組みやZooKeeper,Raftとの類似点と相違点をまとめていて結構良い記事感があります。さすがアリババやで(英語だから翻訳しなきゃならんですが)


## Apache ZooKeeper

* **[Apache ZooKeeper vs. etcd3](https://dzone.com/articles/apache-zookeeper-vs-etcd3)**

⇒ZooKeeperは、設定情報の保持、命名、分散同期の提供、グループサービスの提供のための一元的なサービスです。この種のサービスはすべて、分散アプリケーションで何らかの形で利用されています。

ZooKeeperとetcd(永続的で軽量な分散キーバリューストア)は役割が似ているため、対立構造で紹介されてる記事が多かったです。 **ZooKeeperは古参でetcdは新参** という感じでしょうか。それぞれのメリット/デメリットも記述されていて良い記事です。このように対比しつつ学習したほうが学習効率は良いかもしれないですね。

<details>
<summary>以下記事のDeepL翻訳抜粋</summary>

> ZooKeeperはHadoop、Kafka、Solrなど、Apacheのほとんどのプロジェクトで使用されています。その実績と安定性から、ZooKeeperは世界でもトップクラスの分散調整システムになっています。ZooKeeperはコンセンサスプロトコルとしてZAB (ZooKeeper Atomic Broadcast)を使用しています。

> etcdはGoで書かれています。その主な目的は、ZooKeeperの欠点を解決することです。ZooKeeperほどの歴史と知名度はないが、将来性のあるプロジェクトである。Googleのコンテナ管理プラットフォームとして知られるKubernetesは、etcd v2を分散ストレージとして使用し、マスターコンポーネントの分散ロックを取得しています。
etcd はコンセンサスに RAFT コンセンサスアルゴリズムを使用しており、ZAB プロトコルを持つ ZooKeeper よりも簡単に実装することができます。

</details>


* **[ZooKeeper Internals](https://zookeeper.apache.org/doc/r3.5.0-alpha/zookeeperInternals.html#sc_atomicBroadcast)**

⇒あまり日本語の記事がなさそうに見えたので、ちゃんと公式ドキュメントを見るのが手っ取り早いですね...

<details>
<summary>以下記事のDeepL翻訳抜粋</summary>

> ZooKeeper のメッセージングは2つのフェーズから構成される。
1.リーダ活性化
このフェーズでは、リーダーはシステムの正しい状態を確立し、提案を開始する準備をする。
2.メッセージ送信の開始
このフェーズでは、リーダーは提案するメッセージを受け取り、メッセージの配送を調整する。

> 1.リーダー活性化
現在、ZooKeeper には2つのリーダー選出アルゴリズムがあります。LeaderElection と FastLeaderElection (AuthFastLeaderElection は FastLeaderElection の亜種で、UDP を使用し、IP スプーフィングを避けるためにサーバーが簡単な認証を実行できる) です。ZooKeeperメッセージは、以下が成立する限り、リーダーを選出する正確な方法にはこだわらない。
・リーダーはすべてのフォロワーの中で最も高い zxid を見たことがある。
・リーダーを支持することを約束するサーバーのクォーラムが存在する。

⇒最も高いzxid(ZooKeeper transaction id)を知っていて、過半数の支持を受けているサーバーならばリーダーになれるってことかな。おそらく

> 2.メッセージ送信の開始
リーダーはすべてのフォロワーに同じ順序でプロポーザルを送信する。さらに、この順序はリクエストを受信した順序に従う。FIFOチャネルを使用しているので、フォロワーもプロポーザルを順番に受け取ることになる。
フォロワーは受信した順番にメッセージを処理する。これは、メッセージが順番にACKされることを意味し、リーダーはFIFOチャネルのため、フォロワーからのACKを順番に受信することになる。

⇒リーダーが決まった後はリーダーからフォロワーに順番に指示出ししていく感じですね

</details>

## etcd

* **[Kubernetes](https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/)**

⇒etcdはKubernetes内部で使用されているので、Kubernetesについてまず理解すると良さそうと思います。ただKubernetes自体が難しい技術なので、いろいろ概念や用語をググりつつ理解していく必要がありそう。公式ドキュメントを載せておきます。


* **[Kubernetes etcd：歴史、進化、使い方について](https://qiita.com/KentOhwada_AlibabaCloudJapan/items/8fcf7925e8df48ab5625)**

⇒このQiita記事は下記のアリババクラウド様の記事を翻訳したものになっているようです。(アリババクラウド様、たびたびお世話になります。良い記事ありがとうございます)

https://www.alibabacloud.com/blog/getting-started-with-kubernetes-%7C-etcd_596292


etcdがRaftアルゴリズムをベースにリーダー選出/データ同期を行っている話や、Kubernetesがどのようにetcdを使用しているのか(サービスディスカバリー/Kubernetesメタデータの保存など)といったことが書かれていてすごく勉強になります。


* **[Kubernetes Leader Election in Depth](https://d-kuro.github.io/post/kubernetes-leader-election/)**

⇒Kubernetesのリーダー選出手順がスライドにまとめてあったりGoの実装を見ていたりして勉強になります。やはり実装とともにリーダー選出手順をみていきたい気持ちがあるのでとてもありがたい記事です。


# 分散システムってやつはね、知れば知るほど飛ぶぞ
ということで、**うっすら表面だけさらって良さそうな記事をピックアップしてみました。**

解釈とかめちゃくちゃ間違ってるかもしれないですが、これから分散システムを学びたいなぁと思っている人にとって、良い記事になれば幸いです。
この記事を書いていて、**分散システムって奥が深いわぁ**と思いました。

**「次のリーダーに俺が立候補したるで」** って感じでキャンペーンしてリーダーになったり
**「おまいらちゃんと生きてるかぁ」** ってお互い疎通しあってるのとかを擬人化して考えると、ちっちゃい社会の縮図みたいでかわいく思えてきますね。

読んでいただきありがとうございました。