メインコンテンツへスキップ

ブロックチェーンとデータベース:虚を極め、静を篤く守る

陈天(ArcBlock 区块基石研发副总裁)
ブロックチェーンデータベース

著者: 陳天(ArcBlock 研究開発担当副社長)

はじめに:サトシ・ナカモトがビットコインのホワイトペーパーを発表してから10周年を記念し、ArcBlock 研究開発担当副社長の陳天が、ブロックチェーンとデータベースの関係についての独自の観察と思考を綴った。

10月31日、陳天はモーメンツに、ブロックチェーン事業に身を投じて「半年が過ぎ、血気盛んだった数多くの午前3時グループはひっそりと姿を消し、バブルの中で背泳ぎをしていた大勢の投機家も消えた。それでも私は、ウサギの穴に飛び込んだアリスのように、この不思議な世界を歩き回っている……」と感慨を綴った。

ニュートンの古典物理学が低速環境におけるアインシュタインの相対性理論の一つの現れだとすれば、私たちがよく知るデータベース技術は、弱分散環境におけるブロックチェーン技術の特殊な一例だと考えられる。

「弱分散」環境というのは私がでっち上げた言葉で、ノード数が極めて限られ、実行環境が高度に制御された分散環境だと理解してもらえばよい。データベースクラスタが同じデータセンターで稼働していても、異なるデータセンターで稼働していても、同じ管理者のもとにある限り、それは制御可能な実行環境である。制御可能な実行環境では、「悪意ある」ノードは存在しないことが前提なので、BFT(Byzantine Fault Tolerance)は問題にならない。したがって複雑なコンセンサスアルゴリズム(consensus algorithm)は不要で、通常は二相コミット(two phase commit)または paxos / raft で合意を収束させ、要件を満たせる。つまり、データベースのコンセンサスアルゴリズムは、ブロックチェーンのコンセンサスアルゴリズムの特殊例である。

ブロックチェーンの世界では、トランザクション(transaction)と、トランザクションが生み出す状態(state)は厳密に分離されている。複数のトランザクションは、コンセンサスアルゴリズムによって選ばれたマイナーに検証され、ブロック(block)にまとめられてブロードキャストされる。その後、ネットワーク内のほかの参加者がブロック内の各トランザクションの正当性を検証し、自分の state db に書き込む。bitcoin では state db は UTXO であり、ethereum では world state である。

データベースの世界には、ブロックチェーンのトランザクション記録に相当するものがないように見える(データベースにおける transaction は別の概念だ)。しかし、よく考えると、そのトランザクション履歴は実は WAL(Write-Ahead Logging)である。外部からリクエストを受け取ると、データベースはまずそれを WAL に書き込み、永続ストレージに入ったことを保証してから、自身の “states” に書き込む。この観点から見れば、WAL の各レコードはブロックチェーンの一つのトランザクションに対応しており、ブロックチェーンのトランザクションの特殊例だと考えられる(もちろん、二つの checkpoint の間を一つのブロックと見なせると argue してもよい)。

さらによく考えてみると、WAL、blockchain、そして Martin Fowler がずいぶん前から提唱していた CQRS(Command Query Responsibility Segregation)は、このレベルでは実のところ「一本の幹から分かれた枝」である。いずれも「イベント」と「状態」の分離を重視し、直前の状態 + 現在のイベントから現在の状態を導き出せる。したがって、初期の「状態」を一つ用意し、システムで発生したすべての「イベント」を記録しておけば、任意の時点の「状態」を復元できる(CQRS に興味があるなら、私たちの arcblock tech learning series: CQRS & Commanded をお見逃しなく)。

トランザクションと、それを収める「ブロック」に話を戻そう。「ブロック」は奇妙な存在だと気づくだろう。なぜデータベースには「トランザクション」を収める容器として「ブロック」のような概念が不要なのに、ブロックチェーンには必要なのだろうか。ブロックチェーンの世界では、不確実性と確実性はまるで双子の兄弟であり、確実なのはルール、不確実なのはルールの実行者である。いわゆるマイナーが持ち回りで担当し、次は我が家の番となるわけだが、では一つの「ラウンド」をどう定義するのか。この問いに答えるには、あるラウンドにおけるマイナーの地位の始まりと終わりを明確にする仕組みが必要であり、その始まりと終わりこそが一つの「ブロック」である。それだけではない。物理時計が一致しない分散環境では、「ブロック」はグローバルクロックの役割も担い、カチカチとネットワーク全体を前進させる。「ブロック」という概念はそれほど重要だからこそ、当然のようにコンセンサスアルゴリズムの基礎となる。まず次に生成されるブロックの番号について合意しなければ、このゲームは進められない。一方、データベースシステムでは、データベースクラスタ内の master(マイナーに相当)は固定されている。master が号令をかければ slave は素早く追随し、指示どおりに動く。持ち回りで主役になることもなければ、ラウンドも存在しないので、実際には各「トランザクション」が一つの「ブロック」となる。つまりデータベースの世界では、論理的には各トランザクション、言い換えれば WAL の各レコードが、それ自体で暗黙の「ブロック」を形成している。

この結論を別の角度から検討してみよう。「ブロック」のもう一つの重要な役割は crash recovery である。ブロックチェーンネットワークでは、あるノードがネットワークから切断された場合でもクラッシュした場合でも、その状態は必ずネットワーク内で合意された状態と一致しなくなる。では、この不一致な状態から、同期した状態へどう復旧するのか。答えは「ブロック」である。それが、合意によって生まれた唯一の明確な成果だからだ。ノードは、commit 済みでネットワークと一致する直近のブロック高を必ず見つけられる。そしてその高さ以降をブロック単位で同期し、各ブロックに含まれるすべてのトランザクションを順番に実行してローカルの状態を更新することで、最終的にネットワーク内の状態との一致を保証できる。ここでは、「ブロック」が状態の一致を検出し、実現する最小単位である。一方、データベースシステムでは、クラッシュ後にほかのノードから最新の WAL を同期し、前回 commit した WAL の位置以降のコマンドをレコード単位で、すべてのレコードを実行し終えるまで実行する。この時点で、データベースの状態はクラスタの現在の状態へ復旧する。ここでは、WAL のレコードが一致を検出し、実現する最小単位なので、これを暗黙の「ブロック」と呼んでも何の問題もない。

ブロックチェーンの世界では、一つのトランザクションを検証する必要がある。ここでいう検証には二つの意味がある。1) 本人確認 —— トランザクションがその発信者によって正しく署名されていること。2) 整合性検証 —— トランザクションによる状態変更が正当であること。本人確認は分かりやすい。自分のウォレットの秘密鍵で、私に 1 ABT を送るトランザクションへ署名すると、システムはあなたが本当にあなたであることを検証する。整合性検証とは、states db にあるあなたのアカウントが実際に 1 ABT を超える token を保有していて、初めてそのトランザクションを開始できるという意味である。データベースの世界では、本人確認は RBAC(Role Based Access Control)のようなアクセス制御システムで露骨なほど直接的に解決され、整合性検証はブロックチェーンと似ている。

次に確定性(deterministic)を見てみよう。確定性とは、同じ状態 Sn-1 のもとで、全員が同じトランザクションを受け取り、第三者の情報に一切依存せず独立して実行したとき、その実行結果が完全に一致することをいう。純粋にトランザクションから states db への処理だけを見れば、ブロックチェーンとデータベースはまったく同じで、どちらも確定性を保証できる。しかし、あるブロックチェーンがトランザクションに付加情報を持たせ、その情報によってチェーン上にデプロイ済みのコード(たとえば smart contract)を実行するのであれば、コード自体にも確定性が必要となる点に注意しなければならない。確定性とは、要するに次のとおりである。

コードで不確定な乱数生成器を使用しない —— たとえばコンピュータの時計をシードにして乱数を生成するのは不確定である。トランザクションが実行される瞬間に、すべての参加者の時計が正確に同期していることは保証できないからだ。

  • コードでマルチスレッドの使用を避ける。マルチスレッドによって引き起こされる race condition には不確定性がある。
  • システムクロックを使用しない。説明不要。
  • 初期化されていないメモリを使用しない。そこにエディソン・チャンがいるのか、諸子百家がいるのか、誰にも分からない。
  • 浮動小数点数を使用しない —— これは非常に奇妙だが、CPU arch、コンパイラ、さらには CPU の型番が異なると、サポートする浮動小数点命令セットが異なるため、結果が変わることがある。
  • プログラミング言語の、ランダムな挙動を取り得るデータ構造を使用しない。たとえば map を走査する場合など。

基本的にこれらを避ければ、コードは確定性を持ち、ブロックチェーン上で実行できる。では、なぜデータベースのストアドプロシージャでは、確定性のないコードを実行できるのか。たとえば、ストアドプロシージャ内で現在時刻を使ってレコードを挿入できるのはなぜか。もう一度原点に戻り、「トランザクション」の観点から問題を見ると、ストアドプロシージャは “off-chain” で実行されるコードに似ていることが分かる。データベースに根を下ろしてはいるものの、実際には「トランザクション」の源であり、ストアドプロシージャの実行によって真のトランザクション、すなわち WAL レコードが生成され、それがほかのノードへ同期される。そのため、ストアドプロシージャは non-deterministic でもよい。生成された WAL レコードはすでに deterministic だからだ。現在時刻を含むレコードを追加する際、master での実行時に「現在時刻を取得する」という動作はすでに完了し、確定した値が WAL に格納されている。これはブロックチェーンの smart contract の概念とは本質的に異なる。だからこそストアドプロシージャに確定性は必須ではなく、“on-chain” で実行される smart contract には確定性が必要なのである。この観点からも、データベースシステムは弱化されたブロックチェーンシステムである。

ブロックチェーンとデータベースが保存する対象はいずれもデータである。データの整合性と確定性について述べたので、次はデータの一貫性である。ブロックチェーンは明らかに結果整合性の典型だ。ネットワークが大きく、参加ノードが多いほど、ブロックの伝播は遅くなり、どの時点でも異なるノードから状態を読み取ると不一致が生じる可能性が非常に高い。しかし、ノードが最新のブロックまで同期できさえすれば、ネットワーク全体の状態は収束し、最終的には全員が一貫した状態データを得られる。実は、この理屈に従えば、WAL や CQRS の考え方を採用するすべての分散システムのデータ状態は結果整合的である。これは、古典的なデータベースは強整合性を持つという私たちの印象と一致しないように見える。しかし視点をデータベース内部へ移すと、強整合性は結果整合性にいくつかの条件を加えたものにすぎず、その特殊例であることが分かる。あるブロックチェーンが次の条件を満たすと仮定しよう。

1.どのノードも新しいブロックを受け取ったら、トランザクションの実行を完了して states db に書き込んだ後で、マイナーノード(実際には現在の master)へ確認を送信しなければならない

2.マイナーノードはすべての確認を受け取った後、そのブロックが全員によって正常に commit されたことをネットワーク上の全ノードへブロードキャストする

3.あるブロックについてマイナーノードから上記のブロードキャストを受け取るまで(書き込みが完了するまで)、クライアントから送られたクエリはキューに入って待機する(実際には read-write lock)

そうすれば、外部から見たとき、それも強整合性を持つ。もちろん、3点目はいささか厳しすぎる。一般的なデータベース実装では MVCC(Multiversion concurrency control)を採用し、各 client に現在の状態の snapshot を見せるため、全員が見るデータが一致しないごく短い時間枠が存在する。厳密に言えば MVCC は強整合性とは言えないが、もちろんそう考える人はいない。

上記のルールによって、データベースはある程度の性能を犠牲にして、外部に対する強整合性を実現できる。しかし、ときには何らかの崇(う)高(さんくさ)い理想のために、データベースシステムがこうしたルールを破り、より高い性能をうたうこともある。mongdb は cluster 環境で、書き込み操作がノードの確認を待たずに返るようにできるため、シュレーディンガーの猫のような、聞こえのよい「弱整合性」が生まれた。

ブロックチェーンネットワークは理論上、上記のルールによって外部からは強整合的に見えるよう装うことができるが、実際には運用不可能である。ネットワークが大きいほど遅延も大きくなるため、実用可能な強整合性は、ノード数が少なく、かつすべてのノードが同じ data center にある環境でしか実現できない。データの一貫性という観点からも、データベースは特殊な場面におけるブロックチェーンの一例である。

最後に性能について話そう。性能はネットワーク規模に反比例する。主な理由は二つある。1) ノードが多いほど、合意形成が難しくなる。2) ノードが多いほど、「トランザクション」がネットワーク内を伝播するのに時間がかかる。それでは、宇宙最強の TPS(Transactions Per Second)を達成するにはどうすればよいのか。実は難しくない。データベースが弱分散環境における特殊例なのだから、ブロックチェーンをデータベースの方向へ退化させればよい。PoW は「王侯将相いずくんぞ種あらんや」と唱え、ネットワーク全体を鉄の玉座の争奪戦に参加させる。PoS は「一部の人を先に豊かに」し、DPoS はさらに一歩進んで「指導者を先に行かせる」。近い将来、誰かが究極の大技をひねり出し、ネットワーク全体に唯一の絶対君主を置き、データベースで使える技、replicaSet(やはり HA くらいは必要だ)、Sharding などをすべて投入し、さらに兵法の、戦わずして人の兵を屈する術、「今、水軍八十万を整え、将軍と呉に会猟せん」まで使うかもしれない……そうすれば、堂々と性能の栄冠を奪うことができる。

ただし……映画『狙った恋の落とし方。』で車暁が葛優に尋ねたように、「あのことって、そんなに面白いの?」

このページに関わるもの

用語

  • ブロックチェーン

    記録を暗号学的に結び付け、共通の検証・合意形成ルールに従って取引履歴を確定する分散台帳。