【技術書感想文】データ思考アプリケーションデザイン


読んで非常に良かったので、まとめとお薦めを書きました！


## 本の概要

特定の設計思想や技術について説明する本というよりも、「データを扱うシステムにおいて考えること」を全て網羅したような本です。
この本は、アプリケーション開発をデータ軸で整理し、スケーラビリティ・耐障害性・変更可能性といった性質を実現するための本質的な課題を議論します。
ほとんどのアプリケーションはデータを入力し、データを保持し、そのデータを検索し、そのデータを表示するという機能を持っているので、ほぼ全てのアプリケーション適用できるような大事な考え方を網羅しています。

重要なことはこれらの課題が「特定の技術の課題」や「技術の進展によって解決できる課題」ではないことを議論している点です。
近年、NoSQL系Databaseや分散Node Database、イベントソーシングなど、たくさんの技術が可用性・スケーラビリティのために出現してきています。
これらの技術は、特定の課題を非常によく解決するものですが、全ての課題の解決にはなりません。
この本では、これらの技術が「全ての課題の解決」にはならず、「さまざまな課題のトレードオフ」になることを体系的に説明していきます。

語り口は、技術者というよりも研究者に近く感じました。
「パット使える解決策を提示する」というよりも、「体系的な理解を促し、正しく理解する」ことを目的としています。
なので、技術書として読むと少し読みづらく感じるところもあるかもしれません。
ただ、具体例や図表をしっかりと使い整理しているので、内容の難易度と比べると理解しやすいかと思います。

### 第1部: データシステムの基礎

第1部は「データシステムの基礎」と命名され、「信頼性・スケーラビリティ・メンテナンス性」などから入りDatabaseの仕組みについて触れています。
Databaseについても、SQL系のDatabaseではindexが内部でどのように保持されるか？や、データがどのようにエンコードされるか？など細かいところまで詳しく解説しています。

### 第2部: 分散データ

第2部は「分散データ」と称され、データベースを複数のNodeに分散する場合の技術・課題が出てきます。
分散Databaseでは、Node間の通信が断絶したり通信が遅くなったり、あるNodeが落ちていることもあり得ます。
分散することの目的は可用性を高めることなので、そのような場合でもDatabaseは最小の影響で稼働し続ける必要があります。
この課題についての議論と解決技術が議論されます。

まず、Databaseを分散化する方法は、Leader（書き込みを受け付けるNode）の数によって分類することができます。
Single Leaderでは書き込みを受け付けるNodeは一つです。この場合、発生する課題は「Leaderが受け付けた変更をどのタイミングでFollwer（その他のNode）に伝播させるか？」という問いです。
より正確には書き込みをしたクライアントに対して「完了」のレスポンスを返す前にFollwerが変更を受け取るのか？後で受け取るのか？です。
完了レスポンスの前に変更を伝播させる場合は、Node間のnetwork遅延やFollwer Nodeの障害によって書き込みが停滞してしまいます。また、LeaderがFollowerに変更を伝播させた後、Followerから書き込み完了のresponseが返ってこなかった場合に、Followerが書き込みを実際に完了したのちにクラッシュしたのか、書き込みできずにクラッシュしたのかをLeaderが知る由はありません。この場合、Leaderは書き込みに失敗したと判断して自身の変更を取り消しクライアントには失敗したとレスポンスを送るでしょう。しかし、もし実はFollowerが書き込みに成功していたとすると、Nodeごとに持っているデータが異なってしまいます。
逆に、完了レスポンスの後で変更を伝播させると、完了レスポンスを受け取った直後にFollwer Nodeに問い合わせると変更を受け取っていない可能性があります。

Multi-Leaderの場合、問題はさらに複雑化します。同一のRecordに対するアクセスを複数のNodeが同時に受け付けてしまう可能性があるからです。この場合、Recordの最新の状態をどちらにするのか？という問いが生まれます。
一つの解決策は、Leaderが全てのNodeに伝播させてから完了Responseを送ることです。複数の変更があればそれに対してどちらが最後の変更なのか？の順番をつけることができます。しかし、Single-Leaderの場合と同じく、Node間のNetwork遅延の問題や、Nodeがクラッシュしたときのデータ不整合の問題を抱えることになります。
もう一つはの解決策は、それぞれのNodeがそれぞれ変更を受け付けておき、後々どちらが最新なのか？について合意するという方法です。
この場合でも、瞬間的には異なったデータが発生してしまうことや、データの制約を満たせなくなる可能性があることなどの課題があります。

さらに、transactionも第2部の大きなテーマです。
「整合性」と呼ばれる概念を深く掘り下げ整理し、それらの整合性をどのような仕組みがあれば達成できるのか？について議論しています。

### 第3部: 導出データ

第3部では、「導出データ」について議論しています。

これは、データを処理し変換した結果を作成する方法を大きくバッチ処理とストリーム処理に分けて議論しています。
ここでは、ストリーム処理について詳しく触れます。

ストリーム処理での課題と、Single-Leader Nodeの課題はにていて、network遅延やnode障害がテーマになります。
ストリーム処理ではEventを作成するプロデューサとそのEventを受けとり処理するコンシューマがいます。
その間にはブローカーがいて、プロデューサからメッセージを受け取りコンシューマに配信しています。
コンシューマはメッセージの処理が完了すると、ブローカーに対して完了のメッセージを送りブローカーはそのEventを削除します。

ここでも、Single-Leader Databaseの場合と同じく、streamを処理している途中でコンシューマがクラッシュした場合を考えます。
このとき、そのEventの処理が完了してからコンシューマはクラッシュしたのか、処理が完了する前にクラッシュしたのか？をブローカーは知る由がありません。ブローカーは処理は失敗したと判断して再度コンシューマにメッセージを再送し、結果同じイベントが複数回処理されることがあり得ます。
このようなパターンに対応するために、「冪等性」が重要視されます。これは、処理を複数回行ったとしても一回だけ行ったときと同じ結果になるような性質のことです。これにより、同一のEventを複数回処理する可能性がある前提でシステムを設計できます。
ここでは、冪等性の実現方法とその限界についても議論されています。

この本の最終章である12章は、「データシステムの将来」と命名され、さまざまなトピックについて今後必要とされるであろう技術や考え方が議論されています。
これまで議論してきた課題や解決策を踏まえ、今は浸透していないが価値のありそうな考え方やシステム設計を列挙して行っています。

## 私が学んだこと

この本から得た最も大きなものは「分散システムの課題とその解決技術」についての「言語化」でした。
多くのNoSQL・分散Database・非同期システムについて、「理解するための型」を得たように感じます。
この本で紹介されているような本質的な課題をそれぞれの技術が「どこはこだわり」「どこは諦め」たのか？という視点で新技術を理解することで、高速にキャッチアップできるようになったと思います。

ここでは、これとは別に読みながら「確かになー」と印象に残っているものをメモ的に書いておきます。

### スキーマオンリード・スキーマオンライト

DynamoDBやMongoDBなど、スキーマレスと言われるDatabaseはこれまでも使っていました。
これらのスキーマレスDatabaseに対して、結局どこかでスキーマを仮定しないといけないんだよなー、、、とあまり価値を感じていませんでした。
どちらかというと、誤って間違ったスキーマのレコードを作成したときにエラーが発生しないことへの恐怖の方が大きいのでは？と思っていました。

この本では、これを「スキーマオンリード」と表現し、「スキーマがない」のではなく「スキーマが暗黙的である」と整理し、動的型付け言語と静的型付け言語の比較と繋げて議論しています。
この整理には非常に納得感がありました。

### リーダー選出問題

これは、一つのLeader（writer）と複数のFollower（reader）instanceがあるような構成で、Leader Instanceに障害が発生して機能しなくなったとき、いかに複数のFollwer InstanceからLeaderを選出するか？という問題です。

普段Aurora Databaseを使ってますが、ここではリーダ選出は自動的に行われます。
なので、このような技術については知っていましたが、そこまで深く考えたことはなく、シンプルに一つ選べばいいんだなーと思っていました。

実際には複数あるfollwer instanceのうちどのinstanceをleaderとして選出し、またその選出についてどのように全てのinstanceが同意するか？という課題は、考えてみると複雑でした。

## こんな人におすすめ・おすすめじゃない？

難しい概念がよく整理された本で、一度読み自分の理解を整理することでできることが大きく増える本だと思います。
サーバーサイドでの非機能要件などの気にする立場であれば特に、スタップアップの過程でどこかでは読んでおくのをお勧めします。

同時に、非常にレベルの高い本でもあると思います。
開発経験があまりない人にとっては「何をいっているのかわからない」「理屈の話ばかりで現実的じゃない」と感じることがあるかと思います。
なので、どういうレベルの人にお勧めなのかを整理しました！

### こんな人にはおすすめ

既に一定の経験を持つ開発者にとっては、技術力をステップアップするためにキーとなる本だと感じてます！
なので、以下のような人には是非是非手にとってももらいたいです！

1. 普段触れているシステムの可用性が課題になっていて、非同期化などを検討している人
1. 非同期システムに触れたことはあるが、あまり自信はない人
1. 分散DatabaseやEvent Sourcingなどの技術を使ってはいるが、その強みをいかせてないと感じている人
1. システム開発には自信があるが「データ」を軸に考えたことがない人

### こんな人には背伸びして読んでほしい

正直レベルの高い本です。以下のような人には「何をいっているかわからない」と感じることもあるかと思います。
それでも、買ってみて眺めてみて「こんな話があるんだなー」と思っておくのは良いと思います！
開発をしながら先輩開発者の説明を聞いて「あの話かも？」と思い出せるだけでも価値は大きいと思います。
また、数年後にもう一度眺めてみると理解できるものが増えて成長を感じるかもです。

1. 開発者として経験を積んできて、可用性などの非機能要件も考えられるようになってきた。
1. 単一NodeのDatabaseなどを使っていて、非機能要件が不安になってきている
1. 非同期や分散という話を聞いてはいるが、なんで必要なのか分かってない

### こんな人にはおすすめしない

この本は初心者向けの本ではないです。
自分の現状から大きく飛躍する本を読んでもよくわからず終わるかと思います。
なので、以下のような人はもう少し経験を積んでから手を出すのをお勧めします。

1. 開発1,2年目の初心者
2. シンプルなDatabaseの扱いに自信がない