All Articles

データ指向アプリケーションデザインメモ3

このページについて

データ指向アプリケーションデザイン読書の記録をつらつらと書いておく

10章 バッチ処理

unixの哲学(簡易)

  • プログラムは1つのことだけをうまくこなすようにする
  • プログラムは他の未知のプログラムの入力となることを想定する

    • 例としては、パイプでつなげるよう、出力は標準出力に書き込む
  • ソフトウェアはせいぜい数週間いないに作れるものをスコープとしておく
  • 手作業をしない。使い捨てになろうとツールを使う

MapReduce

ジョブは1つ以上の入力をとり、1つ以上の出力を生成する。入力データへの副作用はない。 プログラミングフレームワーク ある入力(レコード)に対して、開発者が定義した key-value の値やソートを生成する処理を行う(mapper) mapperによって生成されたデータに対する処理を行うのが reducer
プログラマは上記2つのロジックを実装してデータパイプランを作る

@Todo HDFSって今もポピュラー?基本的にHadoopとはセット?

バッチ処理設計(MapReduce)の注意

ある処理においてなるべくネットワーク越しの通信を行わない。ローカルで処理が完結するのが望ましい。
なので参照系データもなるべくローカルに寄せる仕組みが必要。(ETLプロセス用意など) また、MapReduce処理の出力としては、prod環境のDBなどここでもネットワーク越しに逐次書き込みを行う設計は避ける
その代わり、新しいデータベースをバッチジョブで作成し、分散ファイルシステム中のジョブの出力ディレクトリに書き出す
書き出したものは頃合いを見て、参照系を扱うサーバへバルクロードする こういったデータベースは基本リードオンリーとなっていて、データインポート中には過去の値を返し、インポート後にはアトミックに値を書き換えるといった機能が提供されている(Voldemortの場合)。基本ジョブが最初に書き込んだデータに対してのみ動き、immutableを守るようにできている データソースをimmutableに保つので、なにか途中でロールバックせざるを得ないときもやり直しをすれば、データソースが変わっていなければMapReduceは結果整合性を保てる。

MapReduceの先

Spark, Tez, Flink のような データフローエンジン
ワークフロー全体を一つのジョブとして定義できる。これまでは、mapperとreducerで細かく分割してきたが、それではある最終アウトプットの途中でのジョブの結果は他のジョブからは参照されないことが多々ある。そういったデータ(中間状態)を実体化するのは too much なので上記のような仕組みが考え出された。(例えば、中間状態をレプリケーションすること) またタスクの依存による待ちが発生してしまっている状況ももったいない。実は、reducerが出力した内容をreducerが受け取ればmapperは不要だったりする。 @Todo Tezとか分散フレームワークはどれが人気なのかgoogle trendsで検索ワード比較してみる

Pregelモデル googleの論文が発祥。ある頂点は別の頂点にメッセージが送れる、グラフ構造のような作りをしている。 そのため、どのようにでもパーティショニングが可能。グラフだからといってあんまり分散させるとマシン間での
送受信オーバーヘッドはそれないになってくる @Todo もうちょっとメリデメ調べる

11章 ストリーム処理

@Todo メッセージブローカの標準. JMS, AMQP調べる

変更データのキャプチャ(change data capture) イベントソーシングなどと関連ありそうな話題。 データベースに書かれたすべてのデータの変更を観察し、それを他のシステムへレプリケーションできる形態で取り出すプロセス。 データのイベントに対するトリガが仕込めるようになっているぽい
postgres で cdc
ログはパースしないとダメっぽい。

@Todo

  • LinkedIn の Databus
  • Facebook の Wormhole
  • Yahoo!の Sherpa

@Todo VoltDB では、ストリーム形式でデータベースから連続的にトランザクションがデータをエクス ポートできます [40]

イベントソーシング

アプリケーションの状態に加えられたすべての変更を変更イベントのログとして保存していく
更新や削除は行われないように設計される

  • イベント

    • バリデーションなど通し、コマンドを受け入れたあとのデータ
    • イミュータブル
  • コマンド

    • ユーザのリクエストなど

単一ノードのスループットを超えてスケールで き、地理的に分散している環境でもうまく働く合意アルゴリズムの設計は、現在でも未解決の研究課題

Create Index は簡単に行ってしまえば、DB内の対象レコードを拾って、新たにビューを作ること

@Todo Postgres foreign data wrapper, フェデレーテッドデータベース, フェデレーションとは

安全性は 分散トランザクション < イベントログによる非同期書き込み ログベースにすることで、複数システムを疎結合にできる。連携するシステム同士が共倒れにならないし、メッセージもログベースのキューを使っていれば失われない。

筆者はDB同士がunixのシェルのようにつなぎ合わせられればいいと考えている。 ex. mysql | elasticsearch
これは差分データフローと呼ばれる領域で研究されてるっぽい @Todo

イベントストリームによるアプローチとマイクロサービスによるアプローチ 例えば、常に変わる為替に対して計算を行うユースケースの場合、マイクロサービスでは都度DBに問い合わせて演算する。しかし、イベントストリームの場合は為替の変更を常にサブスクライブしてローカルに保持しておけば問い合わせがいらない。 マイクロサービスでもredisに書き込むサービスがいれば同じだろうけど、どっちが一般的なんだろ。要は通信減らせればgoodなんだけど。データフローをアプリケーションで実現させようという設計方針。 UIもリクエスト/レスポンスのデータフローからサブスクライブ/パブリッシュを利用したほうがインタラクションとしてはリッチになる

@Todo p567 銀行のトランザクション

p568 の 重複ユーザが操作してないか弾く方法は勉強になる

AからBへの送金要求を2つのストリームに分けてしまうの面白いなぁ。分解してそれぞれの処理が責任もって完結させるみたいな。データは最小限に区切って流せるようにしたほうが強いシステムになるのかな。

@Todo Merkle trees

整合性チェック, 監査のアルゴリズムはいろんなサービス参考にしたい。google stackdriver logging とか

感想

一通り読み終えたが、トランザクション周りなどは何回も読み返してかつ動かして理解しとかないとなぁという印象。一応現職で2年ストリーム処理メインのバックエンドをやってきたので後半はわかる部分が多かったが前半は苦しかった。その分発見もあり面白かったが。。多分このへんはqiitaの記事にあるようにソシャゲとか、toCサービスをガッツリやってきたバックエンドの人にとってはわかりみが深いのかもしれない。次の会社では、トランザクションやストリームなどサービスが大きくなるにつれてデータの量も気をつける部分も増えていくと思うので、設計から強いシステムにしていけるように頑張っていきたい。この本一冊理解しているバックエンドの人は相当強いだろうな。。