読書メモ:データ指向アプリケーションデザイン
このスクラップで読んでいく本について
信頼性、スケーラビリティ、メンテナンス性について
信頼性
信頼性とは
- ユーザーの期待通りに動作する
- 想定外の利用をされても壊れない
- 想定内の負荷やデータ量において問題なく動作する
- 攻撃に耐えうる
信頼性を高めるには
- ユーザーが間違いを起こしにくい設計やインタフェースにする
- 例
- 好ましくないリクエストが送られたら Bad Request を返すAPI
- 例
- サンドボックス環境を活用する
- 例
- API の利用方法を試すためのサンドボックス環境
- 例
- 徹底的にテストする
- 例
- 自動テストの活用
- 十分な QA 期間
- 例
- ヒューマンエラーから即座にリカバリできるようにすることで影響を最小にする
- 例
- 設定変更を即座にロールバックできるようにする
- 新規コードの徐々に行う(想定外のバグが起こるユーザーを最小にする)
- データの破壊に備えて、再計算用ツールを用意する
- 例
- パフォーマンスやエラー発生率をモニタリングできるようにする
- 例
- モニタリングツールの導入
- 例
- 優れた管理方法とトレーニングを実施する
信頼性、スケーラビリティ、メンテナンス性について
スケーラビリティ
考えかた
-
ある側面においてサービスが成長した際、どのように対応すべきか
-
どのハードウェアリソースをどれだけ追加すればよいのか
-
Twitterの例
- 書き込みに比べて読み込みの回数が圧倒的に多い
- RDBでは読み込みリクエストをさばききれない
- キャッシュを用いて読み込みを高速化する
- ユーザーがツイートしたら、それをフォロワーのキャッシュへポストする
- フォロワーはタイムラインを見るときにキャッシュを参照する
パフォーマンスの表現方法
-
バッチ処理の場合
- スループット(単位時間毎の処理レコード数や、1データセット毎の処理時間)
- レスポンスタイム
-
利用する値
- 算術平均値よりもパーセンタイルが適している
- SLAの例
- レスポンスの中央値がXms以下
- Yパーセンタイル値がZ秒以下であれば動作中とみなす
- サービスでは最低でもα%の間動作していなければならない
-
用語
- ヘッドオブラインブロッキング(HOLブロッキング)
- 低速なリクエストが少数あるだけで、後続のリクエストが待たされてレスポンスが悪化すること
- ヘッドオブラインブロッキング(HOLブロッキング)
負荷への対処
-
スケールアップとスケールアウト
‐ スケールアップ
- ハイエンドなマシンで対処する- スケールアウト
- 小さなマシンを複数用意して対処する
- 状況により使い分けたり組み合わせたりする
- スケールアウトよりもスケールアップの方が費用対効果が高い場合もある
- スケールアウト
-
エラスティック
- 負荷の増大を検知して、自動的に計算リソースを追加できるシステムのこと
- 長所
- 人間によるキャパシティプランニングをしなくてよい
- 短所
- システムが複雑になる(これにより、想定外のことが起こるケースもある)
信頼性、スケーラビリティ、メンテナンス性について
メンテナンス性
以下を考えると良い
- 運用性
- 運用チームが扱いやすいようにする
- 単純性
- 新しいエンジニアがシステムを理解しやすいようにする
- システムから可能な限り複雑性を取り除く
- 進化性
- 別名
- 拡張性
- 修正の容易性
- プラスティシティ(plasticity)
- 別名
運用性
-
運用チームの役割
-
システムのモニタリングと、異常事態からの復旧
-
ソフトウェアやプラットフォームを最新の状態に保つ
-
システムの相互作用に注目し、問題を予見した場合は回避策を講じる
-
キャパシティプランニング
-
設定変更時のセキュリティメンテナンス
-
運用で想定外のことが起こらないようにプロセスを定義して、本番環境を安定させる。
-
人材の出入りがあっても、システムに関する組織の知識が保たれるようにする。
-
データシステムにおいて、運用チームの負担を下げる方法(優れた運用性)
- システムにおけるプロセスの状態やパフォーマンスを可視化するツールを導入する
- 自動化と標準的なツールの連係動作を支援する
- 特定のマシンに対する依存性を下げる。別のマシンにしても、システム全体を中断せずに済む。
- ドキュメントと運用モデルを理解しやすいようにする
- デフォルトの挙動を優れたものとして、必要に応じて挙動が上書きできるようにする。
- 自己回復を提供しつつ、必要に応じて管理者によるシステム制御も可能にする。
- 挙動を予想しやすいようにする。
-
システムを複雑にする要因
- 密結合
- 依存関係のもつれ
- 一貫性のない命名
- 特定の問題に対処するためのハック
-
複雑さへの対処法
- 抽象化
- 疎結合
-
変更への配慮(進化性)
- アジャイルな仕事のパターン
- TDD
- リファクタリング
信頼性、スケーラビリティ、メンテナンス性について
まとめ
- 機能要求と非機能要求
- 非機能要求
- 信頼性
- 問題が起きてもシステムが正しく動作できるようにする
- フォールバック
- フールプルーフ
- 問題が起きてもシステムが正しく動作できるようにする
- スケーラビリティ
- システムが成長に対応できるようにする
- スケールアウト
- システムが成長に対応できるようにする
- メンテナンス性
- 保守担当者の負荷を下げる
- システムの状態の可視化
- 自動化
- ドキュメントや運用モデルの整備
- 保守担当者の負荷を下げる
- 信頼性
- 非機能要求
データモデルとクエリ言語
リレーショナルモデルとドキュメントモデル
リレーショナルモデル
- 汎用的に利用できる
- データの量や構造次第ではスループットに難あり
- クエリによってはうまくサポートできない
- インピーダンスミスマッチ
ドキュメントモデル
- インピーダンスミスマッチの解消
- 柔軟なスキーマ
- データ構造によっては非常にシンプルなクエリで済む
多対一と多対多の関係
- リレーショナルデータベースでは容易に表現できる
- 主キーと値を利用する
- ドキュメントモデルにはうまく適合しない
- 更新のコストがかかる
ネットワークモデル
- 別名:CODASYL モデル
- レコードが複数の親を持つことができる
- 目的のデータにたどり着くために、ポインタのようなものを辿る
- アクセスパス
- 辿る処理が複雑になる
リレーショナルモデル
- テーブルは行の集合。データ構造がシンプル
- クエリオプティマイザによる自動最適化
今日のリレーショナルデータベースとドキュメントデータベース
アプリケーションのコードをシンプルにしてくれるデータモデルは?
-
データがツリー構造で、一度にすべてのデータをロードするような場合
- ドキュメントモデル
- アプリケーションによっては、結合に懸念が残る
-
アプリケーションが多対多の関係が必要な場合
- リレーショナルモデル
-
ハイブリッド
- リレーショナルモデルのなかにドキュメントモデルを入れてしまう
- RDBの種類やバージョンでサポート状況が異なる
- リレーショナルモデルのなかにドキュメントモデルを入れてしまう
データのためのクエリ言語
- SQL
Web
- CSS
- XPath
MapReduce
- 処理対象データをキーと値に分ける
- 並列処理を行うための関数を用意する
- 前述の関数を使って、処理対象データを1つ以上のマシン上で並列処理する。
- 計算が終わったデータは reduceを用いて集計する。
グラフ型のデータモデル
プロパティグラフ
-
構成要素
- 一意な識別子
- 外向きの辺の集合
- 内向きの辺の集合
- プロパティのコレクション(キーと値のペア)
-
辺の構成要素
- 一意な識別子
- 辺の始点
- 辺の終点
- 頂点間の関係を分類するラベル
- プロパティのコレクション(キーと値のペア)
RDBで表現することもできる(プロパティグラフはJSON型などを利用する)
- Neo4j 用のクエリ言語
SQLでのグラフクエリ
- Cypher に比べると複雑
トリプルストアとSPARQL
- トリプルの例
-
(Jim, Likes, banana)
-
lucy a person
-
lucy name lucy
-
まとめ
データベース | 想定しているケース |
---|---|
ドキュメントデータベース | データが自己完結している |
グラフデータベース | あらゆるもの同士が潜在的に関係している |
データベースを駆動するデータ構造
ハッシュインデックス
コンパクション
ログのデータ構造
SStableと lsm ツリー
SsTable
- ソート済み文字列テーブル
- セグメントのマージを効率的に行うことができる
- 全てのキーをメモリに保持しておく必要はない
- 範囲 検索に強い
書き込みについて
- インメモリツリー(memtable )に追加する
- memtableが閾値を超えた場合は SSTableとして 永続化する
SSTableからのLSMツリー作成
LSMツリー:Log Structed Tree
- 存在しないキーを探すのに時間がかかる
- ブルーム フィルターと併用すると良い
- 集合の概要を保持するデータ構造
Bツリー
- ほとんどのrdb のインデックスの実装
- キーと値のペアをキーでソートされた状態で保持する
- データベースを固定 サイズのブロック あるいは ページに分割する
BツリーとLSM ツリーの比較
項目 | Bツリー | LSM ツリー |
---|---|---|
書き込み | △ | ◯ |
ファイルサイズ | △ | ◯ |
コンパクションによる読み書き性能低下 | - | ✗ |
トランザクション制御 | ◯ | △ |
その他のインデックス
セカンダリインデックス
- RDBでは特に有効。結合を効率化できる。
インデックスへの値の保存
- 検索する対象
- キー
- 値は以下のいずれか
- 行
- 行への参照
- 行が保存されている場所:ヒープファイル
参照をたどる回数が増える場合への対処
クラスタ化インデックス
- インデックスの中に、インデックス付けされた行を保存する
- 読み込み速度は上がるが、ストレージを余分に消費する
カバーリングインデックス
- テーブルの一部の列をインデックスに保存する
- 読み込み速度は上がるが、ストレージを余分に消費する
複合インデックス
複数の列を対象にしたインデックスのこと。
連結インデックス
複数列を連結してキーにする
全文検索と曖昧インデックス
- これまでに登場したインデックスはあいまい検索にはむかない
- 別の手法が必要
- 全文検索エンジン
全データをメモリで保持する
-
キャッシュに使われるもの
- Memcached
-
耐久性を確保するもの
- 確保する手段
- 特殊なハードウェア
- 変更のログをディスクに書く
- 定期的にスナップショットをとる
- メモリの状態を他のマシンへレプリケーション
- 確保する手段
-
種類
- KVS
- Memcached
- RAMCloud
- Redis
- Couchbase
- RDB
- VoltDB
- MemSQL
- Oracle TimesTen
- KVS
高速な理由
- メモリからディスクへの書き込みが速い
- 書き込み時にエンコードせずに済む
パフォーマンス以外のメリット
- プライオリティキューや集合を実現できる
- ディスクベースのインデックスでは実現が難しい
- Redis
不揮発性メモリ
- 今はまだ研究中。広くは使われていない
トランザクション処理、分析処理
- トランザクション処理
- レコードの挿入や更新
- 分析処理
- レコードの集計
トランザクション処理システム
- 読み取り
- 少数のレコードを検索
- 書き込み
- ランダムアクセスと素早い書き込み
- データの鮮度
- 最新のもの
分析処理システム
- 読み取り
- 大量
- 書き込み
- バルクインサートもしくはイベントストリーム
- データの鮮度
- 過去の履歴
注意事項
分析処理システムとトランザクション処理システムが同一のDBを参照すると、
トランザクション処理システムのアクセス速度が低下する恐れがある
データウェアハウス
- トランザクション処理システムから独立したデータベース
- ビジネスアナリストなどがデータ分析を行うために利用する
データの分析
- 操作
- トランザクション処理とは異なるパターン
- ドリルダウン
- スライスとダイス
- スキーマ
- スタースキーマ
- ファクトテーブルとディメンションテーブルから成る
- ファクトテーブル
- 事実、出来事、数値データ
- ディメンションテーブルテーブル
- 次元、側面、観点など
- ファクトテーブル
- 分析用クエリの実行性能が高い
- データが冗長
- ファクトテーブルとディメンションテーブルから成る
- スノーフレークスキーマ
- ディメンションテーブルが複数のテーブルに分割され、階層構造を形成する
- 正規化されており、ストレージ効率が良い
- クエリの実行速度が遅い
- スタースキーマ
列志向
- 列単位で情報をまとめて保持
- 列単位でのクエリが高速
- データウェアハウスに向いている - 行単位でのクエリは低速
- 圧縮効率が高い
- ビットマップエンコーディング
- ランレングスエンコーディング
集計
- 頻繁に使われる集計をキャッシュ
- マテリアライズドビュー
- データキューブ(OLAPキューブ)
- ディメンションごとの集計値のグリッド
エンコーディングとデコーディング
- プログラミング言語固有のエンコーディング
- 他のプログラミング言語と互換性がない
- JSONやXML
- 互換性がある
- バイナリエンコーディング
- 種類によって圧縮効率が異なる
- Thrift CompactProtocol
- Protocol Buffers
- フィールド名の代わりにフィールドタグを使うことで圧縮効率を高めることができる
- Avro
- hadoopに適している
Avro
データを書き込むときのスキーマをライタースキーマと言う
データを読み込むときのスキーマをリーダースキーマと言う
ライタースキーマとリーダースキーマは同一でなくても良く、互換性があれば良い
例えば、フィールドの順序が異なっていても問題ない
スキーマのやり取りについて
Hadoopで使われる場合は、ファイルのライターが、ファイルの先頭に一度だけライタースキーマを付与する
レコードごとにスキーマが異なる可能性がある場合は、レコードの先頭にバージョン番号を含め、データベース内にバージョンごとにスキーマを保存しておく
ネットワーク経由の場合、接続確立時にスキーマバージョンを指定する(Avro RPC プロトコル )
スキーマのメリット
多くのRDBは、データ用に独自のバイナリエンコーディングを実装している
これは、いわゆるバイナリJSONよりコンパクトである
スキーマはドキュメントとしても役立つ
データフローの形態
データベース経由でのデータフロー
ロード先のプログラムで列が失われると、それをセーブしたときにも、列は失われる
プログラムの変更に比べて、データベースのデータの変更(マイグレーション)はコストが高い
データベースのスナップショットは、書き出したあとは変更しない。AvroのオブジェクトContainerのようなものが適している。もしくはParquet(列志向フォーマット)など。
サービス経由でのデータフロー
REST,RPC
Webサービス
-
REST
- 設計哲学
-
SOAP
- WSDL(Web Service Description Language)
-
RPC
- 問題点
- ネットワークリクエストは予測不可能
- タイムアウト対策
- リトライ時のべき等性確保
現在のRPC
- Protocol Bufferによる実装
- gRPC
- ストリームをサポート
- gRPC
サービスディスカバリ
クライアントがサービスのIPアドレスとポート番号を見つけるためのもの
メッセージパッシングによるデータフロー
非同期のメッセージパッシング
- メッセージブローカーがある
- 受信側が即座に動作できないとき、メッセージブローカーがばっふとなる
- 受信側のプロセスがクラッシュしたときに、メッセージを再配信すればメッセージが失われない
- 送信側は、受信側のアドレスやポート番号を知らなくて良い
- 一つのメッセージを複数の宛先に送信可能
- 送信側と受診側を論理的に分けることができる
アクターモデル
- 単一プロセス内での並行処理プログラミング モデル
- アクターは1つのエンティティを表現し 何らかの ローカルな状態を持つことがあり 非同期のメッセージの送受信によって他のアクターと通信する
- メッセージが配信されることは保証されない
分散アクター フレームワーク
- アクターモデルを利用してアプリケーションを複数ノードにわたって スケールさせる
- アクターモデルでは メッセージが失われることを前提としている