目的
書籍「データ指向アプリケーションデザイン」を学ぶ機会ができたので、復習・知識の定着を目的として、学習した内容を殴り書きレベルでアウトプットします。
主観で気になった点をメモる形になるので、個人の解釈が強くなると思います。間違った解釈の場合もあり得るため、その点はご了承ください。
本記事の対象者は特におらず基本自分のための記事となりますが、もし本書に興味をお持ちの方がおられましたら、この記事が書籍の購入への後押しになれれば幸いです。
書籍紹介
データ指向アプリケーションデザイン
―信頼性、拡張性、保守性の高い分散システム設計の原理
出版:O'REILLY
発売日:2019/7/18
O'REILLYの出版本は、なんか貫禄があって安心感がある。
目次
第I部データシステムの基礎
1章 信頼性、スケーラビリティ、メンテナンス性に優れたアプリケーション
2章 データモデルとクエリ言語
3章 ストレージと抽出
4章 エンコーディングと進化
第II部分散データ
5章 レプリケーション
6章 パーティショニング
7章 トランザクション
8章 分散システムの問題
9章 一貫性と合意
第III部導出データ
10章 バッチ処理
11章 ストリーム処理
12章 データシステムの将来
1章/週のペースで読んでいく予定で、部単位で記事にしようと考えてます。章を読み終わり次第、随時更新予定です。
第I部データシステムの基礎
1章 信頼性、スケーラビリティ、メンテナンス性に優れたアプリケーション
概要
データ指向アプリケーションの設計を考える上で、それを支える基本的な概念について述べられている。特に、実際に達成すべき目標となる信頼性、スケーラビリティ、メンテナンス性と言った言葉の意味、それら目標をどのように達成すればいいのかを考えていく。
キーワード
信頼性、スケーラビリティ、メンテナンス性
内容
データシステムの考察
今日のアプリケーションは、演算指向からデータ指向に、CPU処理能力の制約の課題からデータ量や複雑さ・変化の速度の課題に変わっている。
- データ指向アプリケーションとして一般的に必要とされる機能
- データベース
- キャッシュ
- 検索インデックス
- ストリーム処理
- バッチ処理
これらを抽象化してデータシステムという。
アプリケーションによって要求も異なるため、それに応じて適切なツールや構築アプローチを選択することが求められる。また、単一のツールではまかなえない場合は、複数のツールを組み合わせると言った難しさも存在する。
ここ数年で出ているツールは多彩なユースケースに最適化されていて、分類の境界線が曖昧になってきている。(例:データストア、メッセージキュー、データベース、キャッシュ)
処理に対する要求が幅広くなり、単一のツールでは満たせない場合が増えていっているが、結果、処理を複数のタスクに分割し、それぞれのタスクをそれに適したツールで効率よく処理するように流れが来ている。
データシステムの設計において、以下3つのソフトウェアシステムにおける重要な課題に焦点を当てる。
- 信頼性 ... システムは、障害(ハードorソフトの障害、ヒューマンエラー)があっても正しく動作し続けるべき
- スケーラビリティ ... システムの成長(データ量、複雑さ)に対して、可能な限り対応可能であるべき
- メンテナンス性 ... システムに関わる人たちが生産的に関わることができるべき
信頼性
信頼性 = 大まかにいって「何か問題が生じたとしても正しく動作し続けること」。
フォールト(問題を起こしうるもの)の存在に対処できるフォールトトレラント(もしくはレジリエント)の性質によって、信頼性を高める。
フォールトは障害と同じ意味ではなく、障害はシステムが必要なサービスの提供を止めてしまうことを指す。つまり、フォールトが障害を引き起こさないような耐障害性の仕組みを設計することが信頼性を考慮した設計にとどまり、具体的にはフォールトを回避するより耐性を持つような設計とした方が望ましいと言える。
フォールトと対処法の例
- ハードウェアの障害
- ハードディスクのクラッシュ、電力網の停電、ネットワークケーブルの切断ミス、など
- 対処法 ... ハードウェアコンポーネントに冗長性を持たせる(ディスクのRAID構成、サーバーの電源の2重化、ホットスワップ可能なCPUを持たせる、など)
- ソフトウェアのエラー
- ソフトウェアのバグ、プロセスの暴走、システム依存のサービスの問題、など
- 対処法 ... 手っ取り早い解決策はあまりない。徹底したテスト、プロセスの分離、計測・モニタリング
- ヒューマンエラー
- オペレータによる設定エラー
- 対処法 ... エラーの可能性が最小限になるようなシステム設計、全てのレベルで徹底的にテスト、障害発生時のインパクトの最小化、優れた管理方法とトレーニング実践、など
最終、信頼性を犠牲にして開発コストや運用コストを下げる場合もあるが、その場合は信頼性を犠牲にしていることを強く意識しておくべき。信頼性の重要度を考えておく。
スケーラビリティ
スケーラビリティ = 負荷の増大に対してシステムが対応できる能力のこと。
システムの稼働において、現在の負荷を簡潔に表現できる必要がある(負荷のパラメータ)。
-
例
- Webサーバのリクエスト数/秒
- DBの読み書き比率
- 同時アクティブユーザ数
- キャッシュのヒット率
- ...
-
パフォーマンスの表現(システム負荷の表現)
- 負荷のパラメータを増やしながら、システムリソース(CPU、メモリ、ネットワークの帯域)は一定のままの場合のシステム性能の影響
- 負荷のパラメータを増やしながら、パフォーマンスを一定に保つためのリソースの増減
- バッチ処理の場合は、スループット
- オンラインシステムの場合は、レスポンスタイム
- レイテンシ...リクエストが処理を待っている時間
- レスポンスタイム...クライアントから見た値、リクエスト処理そのものの時間+ネットワークやキューイングによる遅延
-
レスポンスタイムは、計測可能な分布として考える
- 平均と外れ値と中央値
-
パーセンタイル
- 何パーセントのリクエストがある閾値以内だったかを表す
- 99パーセンタイルが1秒だったら、99%のリクエストが1秒以内に処理されることを表す
- テイルレイテンシとも呼ばれる
- ヘッドオブラインブロッキング...低速なリクエストが少数あるだけでそれ以降のリクエスト処理が待たされる
- レスポンスタイムはクライアント側で計測することが重要
-
負荷への対処
- スケールアップ(マシンスペックを上げる垂直スケーリング)とスケールアウト(複数マシンに分散させる水平スケーリング)
- シェアードナッシングアーキテクチャ...複数マシンへの負荷分散
- エラスティック...負荷増大を検知して、自動的にコンピューティングリソースを追加できるシステム
- 初期段階・まだ検証されていないプロダクトの場合は、通常は仮説に基づく将来の負荷に応じてスケールすることより、プロダクトの機能に関するイテレーションを素早く行えることの方が重要(アジャイル開発的なことと理解)
メンテナンス性
メンテナンスの負担を最小化して、レガシーとなるソフトウェアを生み出すことを避ける設計
-
ソフトウェアシステムのための3つの設計原則
- 運用性 ... システムをスムーズに動作させ続けるために、運用チームが扱いやすいようにする
- 単純性 ... 誰もが理解しやすいシステムにする
- 進化性(拡張性、プラスティシティ) ... 将来の要求の変化によるユースケースに対応しやすくする
-
優れた運用性は、定型タスクを容易にし、運用チームが価値の大きな活動に注力できるようにする。
- 内部の挙動の可視化
- 標準的なツールとの結合のサポート
- 個々のマシンの依存性の排除
- 優れたドキュメンテーション
- 適切な自己回復
- 予想外のことができる限り起きないようにする
-
単純さは、偶発的な複雑さを取り除くということ
- 抽象化
- 実装の詳細の大部分を隠蔽できる
- 幅広い種類のアプリケーションで利用できる(再利用)
-
進化性(アジリティ)
- 変化に適応するためのフレームワークをアジャイルが提供
- 異なる特徴を持つ複数のアプリケーションやサービスから構成される、大規模なデータシステムにいてアジリティを高めるための方法
2章 データモデルとクエリ言語
TBD
3章 ストレージと抽出
TBD
4章 エンコーディングと進化
TBD