はじめに
NoSQLは、かなり大雑把な言い方をすると、RDBから「SQL」と「トランザクション」の機能をなくした代わりにスケーラビリティを確保したものだということができる思います。
前回は、HBaseを「SQL」で操作することができるライブラリ「Phoenix」を紹介しました。今回は、残りの「トランザクション」をHBase上で実現した「Omid」というライブラリを紹介します。
対象読者
- HBaseを使ってみたいけどどう使ったらよいか分からない方
- MySQLなどのRDB以外のデータベースを使ってみたい方
Omidとは
Omidは、Yahooで開発されたHBaseでトランザクションをサポートするライブラリです。Omidは楽観的なアプローチを取っており、実際に更新するときに更新検出を行い、他に更新があった場合はアボートさせるということをします。
分離レベルとしては、Snapshot Isolationが実現されています。
Omidには、トランザクションを管理するThe Status Oracleと呼ばれるサーバ(以下TSOサーバ)が存在します。TSOサーバは、トランザクションに関する情報を管理し、データ更新の競合を監視します。
NoSQLであるHBaseでトランザクションを扱うためには、当然、ある程度のスケーラビリティを犠牲にしなくてはなりません。ドキュメントによると、秒間50,000トランザクションまではスケールアップできるということです。詳細については、以下を参考にしていただければと思います。
トランザクションについて
Omidの詳しい説明に入る前に、簡単にトランザクションについて復習してみましょう。
トランザクションとは、分けることのできない一連の処理の単位のことを言います。トランザクションの例として、銀行の出金処理と入金処理がよく挙げられます。出金が成功して入金が失敗するようなことが起きてしまうと大変なことになってしまいます。
また、たいていシステムでは複数のトランザクションが同時に実行される場合があると思いますが、このような場合にも正しく処理できる必要があります。
トランザクションでは、ACID特性と呼ばれる満たすべき要件があります。
ACIDとは、Atomicity(原子性)、Consistency(一貫性)、Isolation(分離性)、Durability(永続性)の頭文字をとったものです。
-
Atomicity:トランザクション内の処理が、すべて実行されるか、すべてキャンセルされることを保証する性質。
-
Consistency:トランザクション開始と終了時にアプリケーションに応じたデータのルールを満たすことを保証する性質。
-
Isolation:トランザクション中の処理が、同時に実行されている他のトランザクションの影響を受けないことを保証する性質。
- Durability:トランザクションが完了した時点で、それらの処理は永続化され、結果が失われないことを保証する性質。
さらに、Isolationに関しては、分離レベルという、Isolationの程度を表す概念が存在します。分離レベルが厳格なものほど、パフォーマンスがかなり低下していきます。パフォーマンスとIsolationの厳格さとのトレードオフを調節するために、分離レベルという概念が存在するのです。
ANSI標準で定められている分離レベルは、Read Uncommitted、Read Committed、Repeatable Read、Serializableの4つがあります。
-
Read Uncommitted:他のトランザクションでコミットされていない書きかけのデータを読み込んでしまう可能性があります。これをダーティーリードと呼びます。
-
Read Committed:すでにコミットされているデータしか読み込むことはありません。ただし、トランザクション中に他のトランザクションでコミットされる可能性があるため、同じデータを読み込むたびに結果が変わってしまうことがあります。これを、ノンリピータブルリードと呼びます。
-
Repeatable Read:トランザクション中に同じデータを読み込んだ場合は必ず同じ結果が返ってきます。ただし、ファントムリードと呼ばれる他のトランザクションが追加したり削除したデータが途中で見えてしまう現象が起こる可能性があります。
- Serializable:同時に実行されるトランザクションの結果が、どのような場合においても逐次実行した場合と同じ結果を返します。
Snapshot Isolationについて
Omidでは、分離レベルとしてSnapshot Isolationをサポートしていると最初に書きました。
ANSI標準で定められている分離レベルの中には定義されていませんが、Repeatable ReadとSerializableの間の分離レベルになります。
Snapshot isolationでは、すべての読み込みは、データベースのある時点の一貫性のあるスナップショットに対して行われることを保証します。
つまり、あるトランザクション内の読み込みは、どのタイミングでも同じ結果を得ることができます。また、ファントムリードの発生も回避できます。
この分離レベルは、多くのRDBでMVCC(Muilti-Version Concarrency Control)として実装されています。
悲観的なアプローチと楽観的なアプローチ
トランザクションの実装方法として、悲観的なアプローチと楽観的なアプローチがあります。
悲観的なアプローチでは、トランザクション開始時に必要なロックを取り、トランザクションが完了するまでそのロックを保持します。
楽観的なアプローチでは、トランザクション開始時にはロックを取らず、トランザクション完了時に他の更新があるかの検出を行い、更新があった場合はトランザクションをアボートさせます。
通常、悲観的なアプローチは、書き込みの競合が多い場合に有効です。逆に、楽観的なアプローチは、書き込みの競合が少ない場合に有効です。
最初にも書きましたが、Omidは楽観的なアプローチを取っています。