🐕

データ指向アプリケーションデザイン9章

3 min read

9.4.2.5 分散トランザクションの限界(P397)

マクロだとステートフル、ミクロだとステートレスというニュアンス。確かにマクロで見たら、サーバーはオートスケールするのでステートフルの振る舞いになる。

多くのサーバーサイドアプリケーションはステートレスなモデル(HTTPはステートレス指向であるように)で開発されており、永続的な状態は全てデータベースに保存します。これには、アプリケーションサーバーを必要に応じて追加したり削除したりできるという利点があります。

「9.4.2 分散トランザクションの実際」では、ヘテロジニアスな分散トランザクションは実装することが難しい、と記載されている。こちらに関しては、細かい部分が理解できていないので再読が必須。

9.4.3 耐障害性を持つ合意(P399)

過半数が動いていないと、その合意を得ることが難しい。例えば10稼働していたとして、その過半数の5から支持を得られれば合意ができる。この合意アルゴリズムを構築する上で、少なくとも全体の過半数は必要であることを示している。運用ルールに近いイメージ。

もちろん全てのノードがクラッシュし、いずれも動作していないのであれば、いかなるアルゴリズムも一切決定を下すことはできません。アルゴリズムが耐えられる障害の数には限度があります。実際のところ、いかなる合意アルゴリズムも終了性を保証するには少なくとも過半数のノードが正しく動作していなければならないことが証明されています。過半数は、安全にクオラムを形成できます。

9.4.3.4 合意の限界(P403)

ネットワーク障害などが発生すると、リーダーの選出が度々発生して本来行うべき有益な処理の時間が捻出できなくなってしまう。そのトレードオフを考慮して、合意アルゴリズムを実装しないケースがある。こういった事象をオーバーヘッドという。

それにもかかわらず、合意のアルゴリズムはあらゆるところで利用されているわけではありません。このメリットには代償が伴っているからです。

9.4.4 メンバーシップと協調サービス(P404-405)

kafka等が、zookeeperを器用に利用している。zookeeperにアプリケーションのデータを補完するわけではなく、全順序ブロードキャストを利用することで、一貫したデータベースへの書き込み順序を担保している。zookeeperは、指揮官のようなイメージ。

10.1.1.2 ソートとインメモリ集計(P431-432)

Rubyと比較すると、Unixはインメモリで大きなデータセットを扱えたり、ディスクから直接処理することが可能である。Rubyはスクリプト言語であり、PythonやJAVAと変わらない。メモリに近いため、メモリを直接処理するコードがある。Rubyは変換工程が多い分抽象化されており、Unixよりも直感的にわかる部分が多い。しかし変換工程が多いため、時間がかかる。一方でUnixは直感的にわかりにくいが変換工程が少ないため、時間が短縮される。

10.1.2.2 ロジックと結線の分離(P434-435)

Hadoopは分散しているマシン上で動く、連携する仕組みを持ったアプリケーションである。

10.2 MapReduceと分散ファイルシステム(P437)

複数のマシンから構成される一台のコンピュータって感じ。メインコンピュータが各マシンとやりとりをするため、膨大なデータ容量を扱える必要がある気がするのだが、「10.2.1 MapReduceジョブの実行(P437)」の冒頭に記載の通り、1-4のプロセスを順番に行うから、そこまで負荷がかからない。

10.2.1.1 MapReduceの分散実行(P439)

  • 例えばクリックされたURLのランキングを表示する場合、一通りURLを洗い出すプロセスがMap関数。洗い出したURLをユニークなURLごとに纏めて、クリック数と紐付けてそーとするプロセスがReduce関数って感じ。
  • 細かい出力先を気にせずに、設計できる仕組みとなっている。計算過程をmapとreduceに分けており、mapがディスクからの入力をとってくる。そしてreduceはそのキーとあたいを受け取って処理するため、次の処理を知る必要がない。Unixのように一つのことをできるツールを組み合わせて、複雑な処理を可能とする。
  • MapReduceはディスクから渡されたものをキーとバリューにして、中間セットを作る。キーと値のぺを入力としてreduceへわたし、それを出力する。
    参照:https://software.fujitsu.com/jp/manual/manualfiles/m160011/j2ul1930/02z200/j1930-00-01-01-00.html

10.2.1.2 MapReduceのワークフロー(P441)

自由の高いコマンドを実行できる。Unixコマンドより専門特化して、分散処理されている。専門特化のスペシャリスト的なツールが、MapReduceである。やろうと思えば、Unixコマンドを組み合わせることで処理ができそう。

10.2.2.3 関連するデータを同じ場所にまとめる(P445)

キーがアドレスのような振る舞いをするため、わざわざネットワーク通信を必要としていない、ということ。

MapReduceのプログラミングモデルを利用することで、演算処理における物理的なネットワーク通信の側面(データを適切なマシンに送る)は、アプリケーションのロジック(用意できたデータを処理する)から分離されました。

10.2.2.5 スキューの処理(P446-447)

  • reducerにおいてパーティションを実施した際に、特定のパーティションに大きな負荷がかかってしまうから、「破綻してしまう」ということ。

「同じキーを持つレコードを同じ場所に持ってくる」パターンは、大量のデータが単一のキーに関連づけられると破綻してしまいます。

  • こちらの回避策として提案されているのが、skewed/sharded joinメソッド。ホットになったreducerのパーティションにおいてさらにMapReduceで分割してそれぞれで処理を行い、reducerで結合させるイメージ。つまりMapReduceが2回流れるって認識。

10.2.3 map側での結合(map-side join)

  • ブロードキャストハッシュ結合:所謂ふつうのmap処理か?小さなデータセットでメモリ内で処理できるため、一通り読み込んでmap処理を行うイメージ。
  • パーティション化ハッシュ結合:事前準備型のmap処理って感じ。図10-3を例に挙げると、mapperとreducerの両方で偶数もしくは奇数IDのユーザを処理するとしたら、其々で同じパーティションを使うことになる。そのため、読み込むデータ量が減る。
  • map側マージ結合:パーティションかハッシュ結合に近いイメージで、特定のキーに基づいてソートを行うことによって、同じパーティションでmapper/reducer処理を行う。その結果、読み込むデータ量がへる。

10.2.5.1 ストレージの多様性(P454-455)

  • Hadoopと大規模並列処理(MPP)の関係は、NoSQLとRDBみたい。MPPは理想論すぎて、かなり時間がかかるため、使い勝手が悪そう。Hadoopみたいに、とりあえずデータを突っ込んでから考える方が早い。
  • Hadoopは複数マシンから構成されるため、単一マシンでタスクが失敗してもジョブを其々でリトライする。MPPは、タスクが失敗したらジョブ全体をリトライするのはコスパが悪そう。