「データ指向アプリケーションデザイン」 で学んだこと、その２

この記事は、"色んなデータストア触ってみる Advent Calendar 2019" の17日目の記事で、
https://qiita.com/advent-calendar/2019/datastores

10日目のその１の続編になります。
https://qiita.com/seikoudoku2000/items/e5a5388d5f290b4a7b35

今回は私なりに、「データ指向アプリケーションデザイン」で学んだことや感想をもうちょっと具体的に書いてみたいと思います。
https://www.amazon.co.jp/dp/4873118700

具体的には、HBaseというKey-Valueストアと、Elasticsearchという全文検索エンジンという、一般的に捉えられている特性が全く違う分散データストレージを、この本の章目次を抜粋しながら比較しつつ、この本を通すと、どういう切り口でデータストレージを見れるのか、、というのを書いていきたいと思います。
この２つを選択したのは、私自身がこの２つに馴染みがあるという要素が大きいので、脳内で自分が馴染みのあるデータストレージに置き換えてみることで、腹落ち度がググッと増すかもしれません。


# HBaseとElasticsearch(と 時々DynamoDB)を比べてみる
以下、何個か章をピックアップしながら、比較をしていきたいと思います。

## 3章 ストレージと抽出
### 3.1.2 SSTableとLSMツリー
HBaseとElasticsearchを学んでいて、何だか似ているな〜と感じる部分として、メモリに溜め込んで定期的にディスクに書き出すというのと、書き出した後にバックグラウンドでファイルのマージ(HBaseではminor/major compaction、Elasticsearchではmerge/force merge)が行われる所がありますが、それがまさにこのLSMツリー(Log Structured Merge Tree)というアプローチを取っているという所にあります。
LSMツリー自体が大変に奥の深い(完全に理解しきれていない時の言い換え..w)もので、この本の中でも
> 当然ながら、実際にストレージエンジンが良いパフォーマンスを発揮できるようにするには、数多くの細部が大切となります。

と、基本的な所は抑えつつも、詳細についてはプロダクト依存の部分が多そうなので、その辺りは各データストレージのドキュメントなりをあたっていくのが良さそうです。
一例として、HBase自体も、LSMツリーで"良いパフォーマンス"を達成できるように"細部"を改善して進化していったことが、以下の記事から伺い知れたりします。
https://shiumachi.hatenablog.com/entry/20131203/1386081104

一方で、
> 細かな工夫は数多くあるものの、カスケードされたSST Tableをバックグラウンドでマージして行くというLSMツリーの基本的な着想はシンプルで効率的です

という記述もあり、これからは新しいデータストレージに出会った時にLSMツリーベースであるということを知るだけで、多くのことが推測できるようになりそうです。

LSM Tree単体であれば、HBaseの馬本でもそれなりにページを割いて説明されていたりもしますが、複数の分散データストレージが共通して持つ特徴として１つの章としつつ、さらに、「3.1.4 BツリーとLSMツリーの比較」のように、他の方式と比較するという所にページを割いて説明してくれていることで、特定のデータストレージに依らない、一つ抽象度を上げた形でデータストレージを捉えやすくなり、良い章だな〜と思ったのでした。


## 6章 パーティショニング
### 6.3 パーティショニングとセカンダリインデックス
### 6.3.1 ドキュメントによるセカンダリインデックスでのパーティショニング

ここでは、HBase vs Elasticsearchに関して、ドンピシャで、
> 多くのキー・バリューストア(HBaseやVoldemortなど)は、実装が複雑になることからセカンダリインデックスを持っていませんが、 (中略) セカンダリインデックスはSolrやElasticsearchといった検索サーバのレーゾンデートル(存在意義)でもあります。

と書かれていて、ここにこの２つの違いがズバッと書かれているのだなと分かり、↓がほぼほぼその答えになりそうです。

> ドキュメントでパーティショニングされたローカルインデックス

> パーティショニングされたデータベースに対するこのクエリのアプローチは、スキャッタ / ギャザーと呼ばれます。

"スキャッタ / ギャザー"はElasticsearchを学んでいると、よく聞く単語ではありますが、これがパーティショニングされたデータベースに対するクエリのアプローチの一般的な総称である、ってのを知ることで、Elasticsearchを１つ抽象化した形で捉えることができるようになります。

一方で、ではなぜKey-Valueストアとしての使い方に主眼を置くHBaseがこの方式にしないか、、という所に関しては、"6.4 パーティションのリバランシング"(後述)を合わせて読むと、そのトレードオフがだいぶしっくりきました。

### 6.3.2 語によるセカンダリインデックスでのパーティショニング
ここでちょっと横道に逸れて、そういえば、DyamoDBは基本的にはHBaseに近いKey-Valueストアだけど、複数のフィールドでのセカンダリインデックスもサポートしてるよな、、？という疑問が。
この本でも、以下のように書かれてはいますが、あまり突っ込んだ説明は見られませんでした。

> Amazon DynamoDBでは、グローバルなセカンダリインデックスの更新は通常の状況下では１秒よりもはるかに短い時間で更新されるものの、インフラストラクチャにフォールト生じた場合には波及にもっと時間がかかることもあり得ます。 

せっかくなので、もうちょっと詳しい説明ないかな〜とあれこれ探していたら、この動画に辿り着きました。

**AWS re:Invent 2018: Amazon DynamoDB Under the Hood: How We Built a Hyper-Scale Database (DAT321)** (リンクはSecondary Indexの説明箇所からの時間指定付きになっています)
https://youtu.be/yvBR71D0nAQ?t=960

**スライド**
https://www.slideshare.net/AmazonWebServices/amazon-dynamodb-under-the-hood-how-we-built-a-hyperscale-database-dat321-aws-reinvent-2018

詳細は動画を見てもらうのが一番ですが、この２つのスライドだけで、だいぶ雰囲気を感じることができます。（そして、グローバルインデックスを実現するのって大変なんだな、、ってのも十分に感じることができるw）

<img width="513" alt="スクリーンショット 2019-12-17 1.53.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91324/988cb3a0-1293-177d-7ef5-d9ad4432d72a.png">
<img width="512" alt="スクリーンショット 2019-12-17 1.53.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91324/fe32be0e-8dab-ad36-5866-b978d620335d.png">

また、この図と先にも引用したこの文章を組み合わせると、セカンダリインデックス利用を前提としたDynamoDBを採用するにあたっては、それは銀の弾丸ではなく、その書き込みに掛かるコスト(DynaomoDBは書き込みスループットでの課金)、シングルマスターのRDBMSとは違ってIndexへの反映ラグが大きくなる可能性があることを十分に考慮した上でアプリケーションを設計しなければならないことを、直感的に認識できそうです。
> Amazon DynamoDBでは、グローバルなセカンダリインデックスの更新は通常の状況下では１秒よりもはるかに短い時間で更新されるものの、インフラストラクチャにフォールト生じた場合には波及にもっと時間がかかることもあり得ます。 

このAWSの動画/スライドを単体で見たとしても、それは点としての知識に留まりがちですが、この本のストーリーに合わせて見ることで、知識が線になり、より理解が深まったと思います。(私は去年もこの動画を見て、ブクマもしてたけど、ほとんど覚えてなかった💦)

### 6.4 パーティションのリバランシング
### 6.4.1.2 パーティション数の固定
### 6.4.1.3 動的なパーティショニング
Elasticsearchを学び出して、最初の方に知るのが、"6.4.1.2 パーティション数の固定" にあるように、Shard数はindexの作成時に決定せねばならず、後から変更はできないというものです。
> 通常パーティション数はデータベースが最初にセットアップされた時に決められ、後から変更することはありません。

これはHBaseから入ってくると、一瞬不便だな〜と思うけど、先のローカルインデックスの構造を思い返すと、動的にパーティション内のデータを入れ替えてるとローカルインデックスも全部作り直しになるので、まあ、そりゃそうよね、、ってのが、この本を読み進めていると結構一瞬で腑に落ちました。
 (そして、ちょっとElasticsearchに詳しくなっていくと、実際はindexを時間単位orサイズ単位でrolloverさせることで、擬似的に時間ベースorサイズベースでのパーティショニングになるし、実際、スキャッタ/ギャザーの検索特性を考えると、それで十分よねってのが感じられたりもします。)

一方で、HBaseは"6.4.1.3 動的なパーティショニング"にあるように、各パーティションが一定のサイズに収まるように、ミドルウェアの方でよろしくやってくれます。
> パーティションが設定されたサイズ以上に大きくなったら(HBaseの場合は10GBがデフォルトです)、そのパーティションは２つのパーティションに分割され、分割後の双方にほぼ半分のデータが含まれることになります。逆に大量のデータが削除され、パーティションが何らかの閾値よりも縮小したら、それを近接するパーティションにメージできます。

この便利機能、当然のように享受していましたが、先に紹介した、"6.3.1 ドキュメントによるセカンダリインデックスでのパーティショニング"での、HBaseではローカルセカンダリインデックスが存在しないというポイントと合わせると、HBaseがKey-Valueストアとして機能を突き詰めるために、どういうトレードオフを選択したプロダクトであるかというのが、ここまでくると自然と理解できます。

本当はDynamoDBでのパーティショニングについても触れたかったけど、力尽きて調べきれなかったので、とても役に立ちそうな記事のリンクだけ置いておきます。。近々ちゃんと書きたい。

DynamoDBデータモデリング虎の巻：第壱巻 〜前提知識編〜
http://marcy.hatenablog.com/entry/2018/07/31/213705

# まとめ
以上、ちょっと長くなってしまいましたが、HBaseとElasticsearch(と 時々DynamoDB)を、この本の章をツマミ食いしながら比較してみましたが、この視点でデータストレージ見ていけるのは良さそうだ！ってのを少しでも感じてもらえたでしょうか、、？

最後に、この記事を書くにあたって、この本を読み直していたら、いつもはサラッと読み飛ばしてしまう、"はじめに"の所に、私があれこれと書きながら伝えたいと思っていたことが見事にまとめられていたので、少し長いですが引用したいと思います。

> データの処理と保存のための技術は、多様であるとともに急速に進化し続けています。本書が目標としているのは、その中を読者が進んでいくことを手助けすることです。本書は、特定のツールのチュートリアルではなく、無味乾燥な理論で一杯の教科書でもありません。本書では成功を納めたデータシステムの例として、広く利用されている多くのアプリケーション基盤を形作り、実働環境で日々求められるスケーラビリティ、パフォーマンス、信頼性に対する要求を満たしている技術を見ていきます。
本書では、そういったシステムの内部に分け入り、その主要なアルゴリズムを解きほぐし、それらの原理と不可避的に生じるトレードオフについて述べます。その過程で試みるのは、データシステムについて考えるための有益な方法を見いだすことです。すなわち、それらがどのように動作するかということだけではなく、なぜそれらの動作がそうなっているか、そしてどういった問いを投げかけるべきか、といったことを見いだしていきます。
本書を読み終えれば、ある目的のためにはどういった種類の技術を用いるのが適切なのかを的確に判断し、優れたアプリケーションのアーキテクチャの基盤を構築するためのツール群の組み合わせ方を理解できるようになるでしょう。独自のデータベースエンジンをゼロから構築できるようにはなりませんが、ありがたいことにそうしなければならないことはほとんどありません。しかし、自分が構築するシステムの舞台裏での動作に関して直感が働くようになるので、システムの挙動を理解し、優れた設計上の判断を下し、問題があっても解決できるようになるでしょう。

本を読み終わった後に、"はじめに"を読んで、見事に目標達成してるよな〜と思える本当に素敵な一冊！！
そして、↓にふんわりと書いてしまった課題感を見事に表現してくれている、、、！(もっと早くここの記述に気づくべきだったw)
https://qiita.com/seikoudoku2000/items/e5a5388d5f290b4a7b35#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%AE%E9%81%B8%E5%AE%9A%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E3%83%A2%E3%83%87%E3%83%AA%E3%83%B3%E3%82%B0

今回はHBaseとElasticsearchという分散データストレージの極々１部分を例に取り上げての紹介でしたが、分散データストレージに関して他にも色んな視点が書かれているし、もう１つ大きな軸として、RDBMSのトランザクションについてや、トランザクションを分散データストレージで実現するにあたっての課題、マルチリーダー(multi leader)なデータストレージがとっている戦略、レプリケーションについてなどなど、それなりの規模のアプリケーションになってくると、気になる/一度はハマるポイントのそれぞれの仕組みとトレードオフや、こういうの知りたいな〜と思いながら中々まとまった分量の文章を見つけられず断片的な知識に終わりがちだったポイントも、色々と書いてくれていて、その辺りも凄く面白かったです。

色んなデータストレージに触れてきて何となく分かってきた気もするけど、さて、こっから先ってどうやって登っていくといいんかな〜と、うっすら感じていた閉塞感を破る手かがりとなるとともに、繰り返し読み直してしっかりと内容を理解し、現場での設計や開発にしっかり役立てていきたい、、と思えた、本当に読み応えのある１冊でした。相当な分厚さで、中々に敷居が高い本ですが、似たような課題感を持ってる人にはひたすらオススメな一冊だし、私自身、あまりに感動したので、２回に渡ってあれこれと書いてみました。

では、この記事を読んでくれたみなさま、Happy databasing!