ゼロから始めるアーキテクチャ学習#
アーキテクチャの基礎#
概念#
-
システムとサブシステム
システム:関連する個体の集まりであり、特定のルールに基づいて運営され、個々の要素が単独で達成できない作業を完了できる集団を指します。(関連、ルール、能力)
サブシステムも関連する個体の集まりから成るシステムであり、通常はより大きなシステムの一部です。
例えば、WeChat 自体は一つのシステムであり、同時にチャット、サポート、友達の輪などのサブシステムを含んでいます。
友達の輪というシステムは、さらにダイナミクス、コメント、いいねなどのサブシステムを含んでいます。
-
モジュールとコンポーネント
ソフトウェアモジュール:一貫性があり、互いに密接に関連するソフトウェアの組織であり、プログラムとデータ構造の二つの部分を含みます。
ソフトウェアコンポーネント:自己完結型で、プログラム可能で再利用可能な、言語に依存しないソフトウェアユニットとして定義され、ソフトウェアコンポーネントはアプリケーションの組み立てに簡単に使用できます。
例えば、学生情報管理システムは、論理的な観点から分割すると、ログイン登録モジュール、個人情報モジュール、個人成績モジュールに分けられます;物理的な観点からは、nginx、Web サーバー、MySQL に分割できます。
- 論理的な観点から、システムを分割するとモジュールが得られます
- 物理的な観点から、システムを分割するとコンポーネントが得られます
- モジュールを分割するのは責任の分離のためであり、コンポーネントを分割するのはユニットの再利用のためです。
-
フレームワークとアーキテクチャ
ソフトウェアフレームワーク:特定の業界標準を実現するため、または特定の基本的なタスクを完了するためのソフトウェア組織の規範であり、特定のソフトウェアコンポーネントの規範を実現するために、規範が要求する基本機能を提供するソフトウェア製品を指します。
ソフトウェアアーキテクチャ:ソフトウェアシステムの基本構造、これらの基本構造を創造するための原則、およびこれらの原則の説明を指します。
(ソフトウェアアーキテクチャはソフトウェアシステムのトップレベルの構造を指します)
アーキテクチャ設計の目的:複雑さがもたらす問題を解決するため。#
複雑さの源#
-
高性能
-
単一機の複雑さ
- マルチプロセス、マルチスレッド、プロセス間通信、マルチスレッドの同時実行などを考慮します。
-
クラスターの複雑さ
-
タスク割り当て
- 一つのタスク割り当て器が複数のビジネスサーバーに進化し、徐々に複数のタスク割り当て器と複数のビジネスサーバーに発展します。
-
タスク分解
-
複雑なビジネスシステムを小さくシンプルな複数のシステムに分解して協力させる
-
タスク分解が性能を向上させる理由
- シンプルなシステムは高性能を達成しやすい
- 単一タスクに対して拡張でき、システムの分割が細かいほど良い。なぜなら、過剰なサブシステムがあると、ユーザーが一度のアクセスで複数回の呼び出しを行わなければ応答結果を得られないからです。
-
-
-
-
高可用性
-
「冗長性」によって高可用性を実現します。
-
計算の高可用性
-
ストレージの高可用性
-
状態決定の高可用性
- 独裁型:一つの決定者のみが存在し、他は報告者です。
- 協議型:二つの独立した個体が情報を交換し、ルールに基づいて決定を行います。
- 民主型:複数の独立した個体が投票方式で状態決定を行います。
-
-
-
拡張性
-
将来の需要の変化に対応するための拡張能力を提供し、新しい需要が発生したときに、システムは大幅な変更なしで、または少量の変更でサポートできるようにします。
- 変化を正しく予測する
- 変化を完璧にカプセル化する
-
-
低コスト
-
革新によってのみ低コスト目標を達成できます
-
例
- NoSQL(Redis、Memcache など)の登場は、リレーショナルデータベースが高い同時アクセスに対処できない問題を解決するためです。
- フルテキスト検索エンジン(Sphinx、Elasticsearch、Solr)の登場は、リレーショナルデータベースの like 検索の非効率的な問題を解決するためです。
- Hadoop の登場は、従来のファイルシステムが膨大なデータのストレージと計算に対処できない問題を解決するためです。
-
-
-
セキュリティ
-
機能的安全性
- 一般的な XSS 攻撃、CSRF 攻撃、SQL インジェクション、Windows の脆弱性、パスワードクラッキングなどは、本質的にシステムに脆弱性が存在するため、ハッカーに機会を与えます。
-
アーキテクチャの安全性
-
主にファイアウォールに依存し、ネットワークを隔離します。
-
DDos
分散型サービス拒否攻撃(英語で Distributed Denial of Service、略して DDoS)は、異なる場所にいる複数の攻撃者が同時に一つまたは複数のターゲットに攻撃を仕掛けることを指します。または、一人の攻撃者が異なる場所にある複数のマシンを制御し、それらのマシンを利用して被害者に同時に攻撃を行います。攻撃の発信点が異なる場所に分散しているため、この種の攻撃は分散型サービス拒否攻撃と呼ばれ、攻撃者は複数存在する可能性があります。
-
-
-
-
スケール
- 機能が増えるにつれて、システムの複雑さが指数関数的に上昇します
- データが増えるにつれて、システムの複雑さが質的に変化します
アーキテクチャ設計の原則#
適切な原則:適切さはビジネスの先行よりも重要です#
シンプルな原則:シンプルさは複雑さよりも重要です#
演化の原則:演化は一歩での到達よりも重要です#
高性能アーキテクチャ#
ストレージの高性能#
-
リレーショナルデータベース
-
読み書き分離:アクセスの負荷をクラスター内の複数のノードに分散しますが、ストレージの負荷は分散されません。
-
データベース分割:アクセスの負荷を分散し、ストレージの負荷も分散できます。
-
ビジネス分割:ストレージとアクセスの負荷を分散します。
-
問題の導入
-
join 操作の問題
- 元々同じデータベースにあったテーブルが異なるデータベースに分散され、SQL の join クエリが使用できなくなります。
-
トランザクションの問題
- 元々同じデータベース内の異なるテーブルは同じトランザクション内で変更できましたが、ビジネス分割後、テーブルが異なるデータベースに分散され、トランザクションで統一的に変更できなくなります。
-
コストの問題
- 元々1 台のサーバーで処理できたことが、3 台以上に拡張する必要があるかもしれません。
-
-
-
テーブル分割
-
垂直分割:テーブル内のあまり使用されず、大量のスペースを占める列を分割するのに適しています。
-
問題の導入
- テーブル情報が複数のテーブルに分散されるため、元々のクエリが今では 2 回以上必要になる可能性があります。
-
-
水平分割:行データが特に大きいテーブルに適しています。例えば、単一テーブルの行記録が 5000 万条を超える場合。
-
問題の導入
-
ルーティング:水平分割後、特定のデータがどの分割されたサブテーブルに属するかを計算するためにルーティングアルゴリズムを追加する必要があります。
- 範囲ルーティング
- ハッシュルーティング
- 設定ルーティング
-
count () 操作
- 元々テーブルに対して count () 操作を行っていたが、分割後はテーブルの数 * count (*) が必要になります。
-
レコード数テーブル
- 新しいテーブルを作成し、各挿入または削除後のサブテーブルのレコード数を記録します。
-
-
-
-
-
実現方法
-
プログラムコードのカプセル化:コード内にデータアクセス層を抽象化して、読み書き分離、データベース分割を実現します。
-
ミドルウェアのカプセル化:独立したシステムを作成し、読み書き分離とデータベース分割操作を実現します。
-
実現の複雑さ:データベース分割は読み書き分離よりもはるかに複雑です。
- 読み書き分離を実現する際は、SQL 操作が読み取り操作か書き込み操作かを識別するだけで、キーワード SELECT、UPDATE、INSERT、DELETE を通じて判断できます。
- データベース分割は操作タイプを判断するだけでなく、SQL 内で具体的に操作するテーブルや操作関数(count、order by、group by)を判断し、異なる操作に応じて異なる処理を行う必要があります。
-
-
存在する欠点
- リレーショナルデータベースは行記録を保存しており、データ構造を保存できません。
- リレーショナルデータベースのテーブル構造スキーマの拡張は非常に不便です。
- リレーショナルデータベースは大データシナリオで I/O が高くなります。
- リレーショナルデータベースのフルテキスト検索機能は比較的弱いです。
-
-
NoSQL
-
リレーショナルデータベース
-
NoSQL の本質は、ACID 特性のいくつかを犠牲にすることで、リレーショナルデータベースの補償を行うことです。
-
一般的な NoSQL ソリューションには以下の 4 つのカテゴリがあります。
-
K-V ストレージ:リレーショナルデータベースがデータ構造を保存できない問題を解決します。Redis が代表です。
-
ドキュメントデータベース:リレーショナルデータベースの強いスキーマ制約の問題を解決します。MongoDB が代表です。
ドキュメントデータベースの最大の特徴は no-schema であり、任意のデータを保存および読み取ることができ、データ形式は一般的に JSON です。
利点:
新しいフィールドの追加が簡単;
過去のデータが間違っていない;
複雑なデータを簡単に保存できます。
-
列指向データベース:リレーショナルデータベースの大データシナリオでの I/O 問題を解決します。HBase が代表です。
例えば、ある都市の超過重量者の数を統一するには、体重という列のデータを読み取るだけで済みます。
-
フルテキスト検索エンジン:リレーショナルデータベースのフルテキスト検索性能の問題を解決します。Elasticsearch が代表です。
-
-
-
キャッシュ
-
基本原理:再利用される可能性のあるデータをメモリに置き、一度生成し、何度も使用し、毎回ストレージシステムにアクセスするのを避けます。
-
直面する問題
- キャッシュの透過:キャッシュに存在しないデータにアクセスし、ビジネスシステムが再度データベースにアクセスする必要があり、データベースサーバーに負荷をかけます。
- キャッシュの崩壊:単一の高熱データが期限切れになる瞬間、データアクセス量が大きく、キャッシュにヒットしなかった後、同じデータに対して大量のデータベースアクセスが発生し、データベースサーバーに負荷をかけます。
- キャッシュのプリヒート:システム起動前に、関連するキャッシュデータを事前にキャッシュシステムにロードします。
- キャッシュの雪崩:大量のホットデータが同じまたは近い期限を設定されているため、特定の時点でキャッシュが集中して無効になり、大量のリクエストがすべて DB に転送され、ストレージシステムに巨大な負荷がかかり、最終的にシステムがクラッシュします。
-
計算の高性能#
-
単一サーバーの高性能
-
PPC(Process per Connection)、新しい接続があるたびに、その接続のリクエストを処理するための新しいプロセスを作成します。
-
prefork:事前にプロセスを作成し、後で直接使用できるようにします。
-
TPC(Thread per Connection)、新しい接続があるたびに、その接続のリクエストを処理するための新しいスレッドを作成します。
-
prethread:事前にスレッドを作成し、後で直接使用できるようにします。
-
Reactor(非ブロッキング同期ネットワークモデル):コアコンポーネントには Reactor と処理リソースプールが含まれ、Reactor はイベントをリッスンして割り当て、処理リソースプールはイベントを処理します。
- 1. 親プロセス内の mainReactor オブジェクトが select を通じて接続確立イベントを監視し、イベントを受け取った後、Acceptor を通じて受け取り、新しい接続を特定の子プロセスに割り当てます。
- 2. 子プロセス subReactor は mainReactor から割り当てられた接続を接続キューに追加してリッスンし、接続のさまざまなイベントを処理するための Handler を作成します。
- 3. 新しいイベントが発生すると、subReactor は接続に対応する Handler を呼び出して応答します。
- 4.Handler は read → ビジネス処理 → send の完全なビジネスプロセスを完了します。
- 画像
-
Proactor(非同期ネットワークモデル):コアコンポーネントには Proactor と非同期操作処理器が含まれます。
- 1.Proactor Initiator は Proactor と Handler を作成し、Proactor と Handler を非同期操作処理器を通じてカーネルに登録します。
- 2. 非同期操作処理器は登録リクエストを処理し、I/O 操作を完了します。
- 3. 非同期操作処理器が I/O 操作を完了した後、Proactor に通知します。
- 4.Proactor は異なるイベントタイプに応じて異なる Handler をコールバックしてビジネス処理を行います。
- 5.Handler はビジネス処理を完了し、Handler も新しい Handler をカーネルプロセスに登録できます。
- 画像
-
-
クラスターの高性能
-
本質:より多くのサーバーを追加することでシステム全体の計算能力を向上させます。
-
複雑さ:タスク割り当て器を追加し、適切なタスク割り当てアルゴリズムを選択します。(タスク割り当て器は、より一般的には負荷分散器と呼ばれます)
-
バランス分類を担当します。
- DNS 負荷分散:地理的レベルの負荷分散を実現します。例えば、北部のユーザーが北京のデータセンターにアクセスし、南部のユーザーが深圳のデータセンターにアクセスします。
- ハードウェア負荷分散:専用のハードウェアデバイスを使用してクラスターのレベルで負荷分散を実現します。この種のデバイスはルーターやスイッチに似ており、負荷分散のための基本的なネットワークデバイスと理解できます。
- ソフトウェア負荷分散:負荷分散ソフトウェアを使用してマシンレベルの負荷分散を実現します。
-
負荷分散アーキテクチャ
- 実際の使用時には、上記の 3 つの負荷分散方法を柔軟に使用できます。まず、DNS 負荷分散を通じて最寄りの都市のサーバー IP を見つけ、次にハードウェア負荷分散を通じて都市に対応するクラスターグループを見つけ、最後にソフトウェア負荷分散を通じてクラスターグループ内で必要なクラスターを見つけます。
-
負荷分散アルゴリズム
- タスク平分類:ラウンドロビン、加重ラウンドロビン
- 負荷分散クラス:負荷が最も低いものを優先
- 性能最適クラス:応答時間が最も短いものを優先
- ハッシュクラス:タスクのいくつかの重要な情報に基づいてハッシュ計算を行い、指定されたホストにマッピングします。
-
高可用性アーキテクチャ#
CAP#
- CAP 理論
- BASE 理論
高可用性の本質は冗長性によって実現されます#
ストレージの高可用性#
-
一般的な高可用性ストレージアーキテクチャには、主従、主従、主主、クラスター、パーティションがあります。
-
主従複製:クライアントの操作はすべて主機を通じて行われ、従機はバックアップの役割のみを果たし、実際のビジネスの読み書き操作には参加しません。
-
主従複製:主機が読み書き操作を担当し、従機は読み取り操作のみを担当し、書き込み操作は担当しません。
-
主従切り替えと主従切り替え
-
設計の鍵
- 1. 主従間の状態判断:状態伝達のチャネルと状態検出の内容を含みます。
- 2. 切り替えの決定:切り替えのタイミング、切り替えの戦略、自動化の程度。
- 3. データの競合解決:故障した主機が回復した後、データをどのように同期するか。
-
一般的なアーキテクチャ
- 相互接続型:主従間で直接状態伝達のチャネルを確立します。
- 仲介型:主従機間は直接接続されず、仲介に接続し、仲介を通じて状態情報を伝達します。
- シミュレーション型:主従間で状態データを伝達せず、従機がクライアントとしてシミュレーションし、主機に対してシミュレーションの読み書き操作を行い、読み書きの応答状況に基づいて主機の状態を判断します。
-
-
主主複製
- 概念:二台の主機があり、互いにデータをコピーし合い、クライアントは任意の一台のマシンを選択して読み書き操作を行うことができます。
- 多くのデータは双方向にコピーできません:例えば、ユーザー登録 ID、在庫など。
-
データクラスター
-
概念:クラスターは複数のマシンが組み合わさって一つの統一されたシステムを形成します。(主従、主従、主主アーキテクチャは本質的に主機がすべてのデータを保存できるという仮定を含んでいます。)
-
クラスターの分類
-
データ集中クラスター
-
データ分散クラスター
- Elasticsearch クラスター
-
-
分散トランザクションアルゴリズム
-
目的:複数のノードに分散されたデータを統一してコミットまたはロールバックし、ACID 要件を満たすことを保証します。
-
二段階コミット(Two-Phase Commit Protocol, 2PC)
- コミットリクエスト段階とコミット提出段階
-
三段階コミット(Three-Phase Commit Protocol, 3PC)
- 提出判断段階;提出準備段階;提出実行段階。(二段階コミットアルゴリズムに存在する単一障害点の問題に対処するために、準備段階を導入し、コーディネーターが故障した場合、参加者はタイムアウトコミットを通じてブロックを回避できます。)
-
-
分散整合性アルゴリズム
-
目的:同一のデータが複数のノードで一貫性を保つことを保証します。
-
メカニズム:複製状態機械
- 複製:複数の分散サーバーが一つのクラスターを構成し、各サーバーは完全な状態機械の一つの複製を含みます。
- 状態機械:状態機械は入力を受け取り、その後操作を実行し、状態を次の状態に変更します。
- アルゴリズム:アルゴリズムを使用して各複製の処理ロジックを調整し、複製の状態機械を一貫性を保つようにします。
-
アルゴリズム:Paxos、Raft、ZAB
-
-
-
データパーティション
-
概念:データを特定のルールに従ってパーティション分けし、異なるパーティションが異なる地理的位置に分布し、各パーティションが一部のデータを保存することを指します。この方法で地理的レベルの障害による巨大な影響を回避します。
-
考慮すべき問題
-
データ量:データ量が大きいほど、パーティションルールは複雑になり、考慮すべき状況も増えます。
-
パーティションルール:大陸間パーティション、国パーティション、都市パーティション
-
複製ルール
- 集中型:一つの総合バックアップセンターが存在し、すべてのパーティションのデータがバックアップセンターにバックアップされます。
- 相互バックアップ型:各パーティションが他のパーティションのデータをバックアップします。
- 独立型:各パーティションが独立したバックアップセンターを持っています。
-
-
-
計算の高可用性#
-
主従
- 冷備:従機のビジネスが起動していない
- 熱備:従機のビジネスが起動している
-
主従
-
対称クラスター:クラスター内の各サーバーの役割が一致し、すべてのタスクを実行できます。
-
非対称クラスター:クラスター内のサーバーが複数の異なる役割に分かれ、異なる役割が異なるタスクを実行します。
ビジネスの高可用性#
-
異地多活
-
目的:システムレベルの障害に対応します。
-
アーキテクチャ:同じ都市の異なる地区、異なる都市、異なる国。
-
設計のテクニック
-
1. コアビジネスの異地多活を保証する
-
2. コアデータの最終的な一貫性
-
3. データを同期するために多様な手段を採用する
- メッセージキュー
- 二次読み取り
- ストレージシステムの同期
- 遡及読み取り
- データ再生成方式
-
4. 大部分のユーザーの異地多活のみを保証する
-
-
設計ステップ:ビジネスの階層化、データの分類、データの同期、異常処理
-
-
インターフェースレベルの障害対応策
-
ダウングレード:特定のビジネスやインターフェースの機能を低下させることができ、部分的な機能を提供することも、すべての機能を完全に停止することもできます。
- システムバックドアのダウングレード
- 独立したダウングレードシステム
-
サーキットブレーカー:しきい値を設定して、依存する外部システムの障害に対処します。
-
リミッティング:システムが耐えられるアクセス量のみを許可し、それを超えるリクエストは破棄されます。
- リクエストベースのリミッティング
- リソースベースのリミッティング
-
キューイング:ユーザーが長時間待たなければならず、処理を受けるか、長時間待っても応答を得られない状態になります。
-
XMind: ZEN - トライアル版