K
batch of doughnuts
Photo by Jonathan Farber on Unsplash

DDIA 読書ノート 【第10章】

第 9 章が難しかったこともあり、読書ノートがまだ書ききれてないんですが、なんとか完成させようとは思っているのでとりあえず 10 章の話をどうぞ。。

Contents

第 10 章 バッチ処理

第 10 章からはチャプターが変わり、チャプター 3。このチャプターではそれぞれに特性の異なるシステムを組み合わせてより大きなシステムを構築する方法が紹介されている。

システムは単体で全てのニーズに応えることが難しい and/or 非効率なため、どう組み合わせるか、といういうのは見落とされがちだが重要なトピックになってくる。

その中で第 10 章はバッチ処理について。MapReduce に関する話題を中心に展開されている。

Unix 再訪

唐突に感じるところもあるがまず取り上げているのが Unix の哲学とそれに基づいた Unix ツール群、というのも MapReduce はこの Unix の概念や教訓と共通する部分が多いため、馴染みのある Unix がまず最初に取り上げられている。

特に重要なのが Unix がファイルを介した、一様なインターフェイスを持つという点で、MapReduce も同様に分散ファイルシステムをインターフェイスとして、それぞれの Job がお互いを意識することなく入出力をやりとりできるようにデザインされている。

Unix の考え方は様々なところで引用されており、馴染みが深いが、ここにも顔を出すその影響の大きさに改めて驚いた。

この Unix の特徴を踏まえた上で MapReduce の詳細説明に入っていく。

MapReduce について

MapReduce にはその名にあるように、mapper と呼ばれるステップと reducer と呼ばれるステップがある。

mapper では先に触れたように分散ファイルシステム上のファイルを通して受け取る入力のデータを key-value のペアにマッピングする。この key-value のペアはソートされたのち key ごとに同一の reducer に送られる。

reducer では mapper から送られてくる key-value を元に好きなことをすればよく1、例えば検索エンジンのインデックス構築であったり、出力をそのまま key-value ストアのデータとして利用するといった用法があるが、最もよく使われる使い道はなんといっても別の Job のインプットにする、ということだ。

先にも触れたように MapReduce は分散ファイルシステムという一様なインターフェイスを持つ。reducer の出力は入力として受け取ったのと同様に分散ファイルシステムに書き出されるため、次の Job はその入力が前の Job の出力である、ということを知ることなく実行できる。これはまさに Unix ツールがファイルを介して連携している点と対応している。

このように、ユーザーは mapper と reducer で何をするかだけを考えればよく、I/O や分散ネットワークについて頭を悩ませることなく Job と Job を繋ぎ合わせて大量のデータを効率よく処理することができるのが MapReduce の特徴である。

MapReduce は大量のデータに対するバッチ計算処理のフレームワークを提供したわけだが、そのことにより、収集したデータはひとまずどこかに保存してしまい、それを処理するのは別のタスクとして切り出す、というアプローチが広まった。これによりデータの収集よりもデータの解釈に重きが重要視されるきっかけになったり、生のデータの方が加工されたデータよりも有用だ、という考え方(sushi principle、寿司原則と呼ばれる)に繋がった。

MapReduce から時を経て

と、このように MapReduce はデータ処理に対するアプローチを変える画期的なアイデアだったわけだが、論文が発表されたのは 2004 年。それから月日が経ち、MapReduce のある意味シンプルすぎる考え方から発展させて、より最適化が図られた手法が次々と開発されており、今日では MapReduce をそのまま利用する、ということは少なくなっている。

具体的には、MapReduce は Job の都度ファイルへの書き出しが行われるため、読み書きのオーバーヘッドが発生する。Apache Spark や Apache Tez では mapper の出力を別の mapper に繋げたり、reducer の出力を直接次の mapper に繋げたりすることで、DAG(Direct Acyclic Graph: 有向非巡回グラフ)を構築、全体を一つの Job とすることでファイル書き出しのオーバーヘッドを減らす工夫がされている。

この他にも中間層の不要なソーティングを無くしたり、耐障害性を高めるなど MapReduce を元により最適なバッチ処理のプラットフォームが実現されている。

次章、ストリーム処理

このように MapReduce を通して分散バッチ処理について紹介されてきたが、次章のトピックはストリーム処理となる。両者の1番の違いは処理するデータのサイズが事前にわかるかどうか、という点だ。

今回も学びが多かったので、次章もとても楽しみ。

この章に限らず DDIA の本それ自体に対してもそう言えるのだけど、これまでキャリアがかなり計算・ロジック(あるいはオンラインシステムとも言えるかも知れない)の方に偏っているので、データの方の知識・経験も増やしていきたいと思っている。

もしこのあたりのトピックに関しておすすめの本やリソースなどがあれば(Hadoop などの個別トピックでも全然いいので)紹介してほしいです!

Footnotes

  1. といってもそれは冪等な操作に限る。Job が失敗した際、失敗した計算のみを自動で再実行することで耐障害性を高めているため、実行する度に結果が変わる、というのでは困ってしまう。