1. London Tech Talk
  2. 【Bookclub 第四弾】 "Databas..
2025-07-29 26:33

【Bookclub 第四弾】 "Database Internals" #8 振り返り

spotify apple_podcasts
ken
ken
Host

London Tech Talk 名物 Bookclub 第四弾 "Database Internals" 第八章の振り返り収録です。"Distributed Systems - Introduction and Overview" の内容について振り返りました。

冒頭からいきなり脱線して SQLite3 がいかに耐障害性と Simplicity の観点から優れているかについて語ってしまいました。とはいえ、この背景にあるのはいかに Distributed Database Systems を運用するのかが難しいという事実があります。

ようやく本来のトピックに戻り、本章の内容について振り返りました。Two General's Problem や FLP Impossiblity などのキーワードについて紹介しました。

また Bookclub で盛り上がった観点についても紹介しました。Exactly-once delivery / At-least-once delivery やメッセージの順序保証の難しさ、 Backoff / Jitterのようなリトライ戦略の重要性について議論しました。

加えて TGP (Two General's Problem) / BGP (Byzantine Generals Problem (BGP) の違いについても紹介しました。分散環境における合意形成の難しさについて、以前 Ken が執筆した人狼ゲームのアナロジーで語る合意形成のブログにも触れました。

そのほか Bookclub で盛り上がった観点や、次回の Chapter 9 の予定について触れました。

ご意見・ご感想など、お便りはこちらの⁠⁠⁠⁠⁠⁠⁠ ⁠⁠⁠Google Form⁠⁠⁠⁠⁠⁠⁠⁠⁠⁠ で募集しています。

サマリー

今回のエピソードでは、「Database Internals」の第8章である分散システムについて振り返り、データベースの運用や整合性の維持の難しさを考察しています。また、SQLite3のシンプルさとその進化に焦点を当て、AI技術との関連性についても議論しています。「Database Internals」第8章では、分散システムにおける問題、特にExactly Once Deliveryと準序保証の難しさが取り上げられています。また、人狼ゲームのアナロジーを通じて、合意形成アルゴリズムの重要性とその機能についても紹介されています。

00:03
リスナーのみなさん、こんにちは。London Tech Talkへようこそ。
エギリスのロンドンからお届けしています。Ken Wagatsumaです。
分散システムの理解
本日は、London Tech TalkのBookclub、Database Internalsの振り返りを収録していきます。
今回は、Chapter 8、Distributed Systems Introduction and Overviewについて振り返っていきます。
今回の章からは、折り返しということで、Chapter 8から、分散システムにおけるデータベースの振る舞いについて、本章は話を広げていく形になっていますね。
今回の章の目玉は、何と言っても分散システムの難しさを多角的に理解することにあったと思います。
考えるポイントは、それぞれのマシンの状態、ステート、ステートマネジメントですね。
マシンごとに異なる状態を持つのが分散環境ですから、その異なるマシン間の状態をどうやって整合性を保つのか、という問題の難しさをイメージできるかどうかが鍵でした。
例えば、どれがデータベースのリーダーですか、という情報をそれぞれのマシンが別の認識をしてしまったら、データの整合性がとれず大きな問題につながってしまいますよね。
そういった分散環境でデータベースをデプロイし運用していくことによって、いかに難しいのか、そしてそれをどのようなテクノロジーやアルゴリズムで解決しているのか、というのが分かるのが第2部の醍醐味となっています。
第8章から後半にかけての第2部を読むことで、ロンドテックトークのゲストを中心としたディスコードがあるんですけれども、そこでそのブッククラブの参加者同士と読んだ後とか読む前とかに関連記事を共有したりとか議論したりするんですけれども、
SQLite3というのはシンプルでネットワーク通信のないただのファイルなので対象外性も高くて素晴らしいという長文コメントをしてしまったんですけれども、
それを見た参加者の方はその気持ちが第8章以降を読んでいくことで伝わったのかもしれません。伝わるんじゃないかなと思います。
そのディスコードのコメントについて簡単に紹介しますね。
そこでどんなことを書いたかというと、SQLite3について紹介されているスライドを参加者の方の一人が共有してくれて、僕も実はSQLite3をエキサイトしているせいだったので、僕なりの意見を共有させてもらいました。
SQLite3というのは結局はただのファイルなのでシンプルだし、シンプルであるというのが一番だと。ネットワーク通信のないただのファイルなのでレジリエンシーという観点でも高くて素晴らしいみたいなコメントをしたんですね。
SRAなので対象外性というのはなかなか個人的には重要な観点の一つとなっています。
実は僕の理解ですけど、SQLiteにエキサイトしている僕たちのような人たちの背景には少し深い理由があるんじゃないかなと思っています。
それはマイシークエルとかポスグレみたいなクライアントサーバーモデルのRDBMSにとって代わってSQLite3がこれからの覇権を握るぜっていうことではなくて、
SQLite3ってローカルで動かすデベロップメントのツールだと思ってたけど、意外と結構できるじゃんみたいな再発見が背景にあるのではないかなと思っています。
そのシンプルさとかハードウェアの進化と相まって意外とリードさばけるよねとか、意外とライトボトルテックにならないよねみたいなスケーラビリティも確保できる点に注目が集まっているのがここ数年の話なんじゃないかなと僕は思っています。
特にAIアシステットコーディングとか LLM を使ったプロダクションのアプリを作っていくときに個々人の開発スキルっていうのがChart GPT とかはLLM のモデルによってレバレッサレーターとプロトタイピングの速度が圧倒的に速くなってますよね。
その結果、最初からプロダクションにデプロイするツールの候補として、ローカルでポンと置いてすぐに使えるSQLite 3 でデプロイしても最初のプロトタイピングのそこそこスケールが必要なレベルまでは既存のプロダクトを使ってちゃんとスケールするSQLite 3 っていうのがそのテックスタックとして非常に注目されているんじゃないかなと思っています。
だからその AI を中心とするスタートアップとか、小規模なプロトタイプ開発で幅を大き化しているのがSQLite じゃないかなと思っています。
だからもちろんエンタープライズスケールとか、もっともっとレートステージのスタートアップとかでデータベースを RDBMS でデプロイするときに、MySQL とか Postgreのようなクライアントサーバー型のデータベースがなくなるとは思ってないんですけれども、
SQLite 3 が幅を利かせるポイントっていうのがその時代背景の変化によって増えてきたんじゃないかなと思っています。
その中で、最近SQLite が特にスポットを浴びているのは、Tulso という企業が非常に頑張っているからなんですね。
これご存知の方もいるかもしれないんですけど、もともとSQLite 3 は2000年代初頭から長年開発されてきたバックワードコンパチビリティ命みたいな、
そういう広報互換性命みたいな哲学を持つ、その DBMS における枯れた技術ナンバー1といっても過言ではない存在だったんですね。
そのSQLite っていうのはご存知の方も多いと思いますけど、 Firefox とか iOS のモバイルとかもいろんなエンベデッドの組み込みのところで使われている、
かなりデバイス数としては数億単位で世界中で動いているデータベースというか、ファイルシステムといっても過言ではないんですよね。
だからバックワードコンパチビリティを担保するというのがSQLite がこれだけ広がった理由でもあるし、それを広がり続けるために合法互換性を削らないという思想になっています。
これを言い換えると、互換性を考えすぎて新しい機能を全然入れられていないんじゃないかっていうある種のもどかしさも感じている開発者も結構いました。
そんな中、さっき言ったTulsaがDevSQLというSQLiteのフォークを開発し始めたんですね。
これはGitHubでオープンソースになっているんですけど、これは今までのSQLite 3にはなかったオープンソースでモダンな機能をガンガン取り入れていくぞみたいな。
その一方で互換性はそこまで気にしないよという、まさに新しい風を吹き込み始めたんですね。
これがとても理にかなっていて、例えばロンドンテックトークの以前のブッククラブが収録でも話したんですけれども、
その互換性のために例えばSQLite 3にはジャーナルモードっていうコンフィグレーションがあって、
これのデフォルトは、最近で言うとワルを使うことがライトハイトログモードにすることが多いんですけども、
デフォルトは決してワルにはならないという話をしたんですね。
これはデバイスとかエッジの文脈では重要なんですけど、トゥルスとかAIプロトタイピングのように、
ウェブアプリとかプロトタイピングにおけるデスクトップアプリで使うという分では、
最近のマシンのパワーとかトレンドに合わせて新しい機能をデフォルトで積極的に取り入れてほしいというニーズがあるんですよね。
例えばそのトレンドの中でも目玉機能となっているのが、ベクターサポートですね。
ベクターっていうのはベクタライズ化されたデータのことで、
これは例えばLLMベースのアプリケーションを作るときとかに、
例えばテキストデータとか音声データをベクタライズして保存したいみたいな要件がすごいあります。
ベクターデータベースなんてことを聞いたことある方もいると思うんですけども、
ストリングとかバイナリでもちろん表現できるんですけども、
ベクターをデータベースのファーストシチズンとして、
デフォルトネイティブでサポートされたデータ型として扱えることで、
より開発するときによりパフォーマンスの出る形で、
より自然な形でデータベースを使えるっていうところがポイントになってくるので、
最近データベースのスタートアップを見ていると、
どこの会社も投資家とかマーケットからのプレッシャーを受けて、
ベクタライズサポートっていうのはどこもしてます。
これはPOSGREとかも拡張機能でサポートしているわけなんですけど、
ほとんどの人が慣れているRDBMSがベクター化されたデータを保存できるというのは、
AIエンベディングアプリケーションを作る人にとってはとても楽しい機能ですよね。
もちろん大規模になっていれば専用のベクターデータベースを使ったりとか、
そういうケースも出てくるかもしれないんですけども、
最初はSQLite 3にベクターデータを入れちゃえばそこそこ動くんだよっていう、
そういうAIエンベディングアプリが簡単に作れるっていうのは、
これはプロトタイピングのフェーズにおいてかなり重要になってきますよね。
裏側でオープンAIなどを叩いて、
帰ってきたベクターデータ、PDFとか音声などのベクトル化したデータをSQLiteに入れるだけでいいですからね。
さらに最近のトレンドでいうとTorsoだけではなくて、
fly.ioっていうところにSQLite 3のエキスパートが人材がいるんですけども、
彼がSQLite 3を分散環境で動かすのに必要なlightstream.ioというリカバリーツールであったり、
これはfly.ioのプロダクトとして出ているlightfsというファイルシステムとして動くようなコンポーネントがあるんですけど、
もう開発してますと。
これによってDockerに.sqliteファイルをポンと置くだけで作ったプロトタイプが、
もしうまくいって当たって大きくしたいなってなった時も、
すぐにMySQLとかPosgreに移行しなきゃっていうストレスを感じることもなくて、
まずはTorsoとかfly.ioとかでスケールさせればいいかっていうeasyな選択肢が生まれて、
そこそこのスケールまではSQLite 3のままカバーできるようになったよっていうのも、
エコシステムという観点からは非常に大きいんですね。
ということでまとめると、
ハードウェアの進化によってパワフルになってきたSQLite 3が、
AIトレンドの中でベクトル化をサポートしてきたことによって、
AIスタートアップ界隈を中心にエキサイトしている人が増えてきたということなんじゃないかなと僕は思っています。
ということで冒頭からいきなり脱線してしまったんですけれども、
これがこのチャプター8で学ぶ分散システムの難しさとSQLite 3というシンプルなものがいかに現代ニーズにフィットしているかという僕の視点でした。
一人でソロ収録をすると、盛大に脱線しても止める人がいないということです。
分散システムの重要な概念
内容の振り返りに戻ろうと思います。
チャプター8では分散システムにおけるいくつかの重要なキーワードと概念が紹介されました。
まずはFallacies of Distributed Computing。
訳すと分散コンピューティングの誤ビューですね。
誤ビューというのは間違いとか誤りという難しい感じのやつですね。
これはネットワークは信頼できるとか、レイテンシーはゼロだといった分散システムを設計する上で陥りがちな誤った仮定をまとめたものです。
もちろん実際にはネットワークというのは信頼できません。
レイテンシーはゼロにはなりません。
なので待機幅バンドビスも無限ではありません。
そういったその現実を認識してソフトウェアのアーキテクチャに組み込むということが分散システムを扱う上での出発線になりますと書いてあるんですね。
そしていくつかのキーワードも紹介されました。
一つ目がTwo Generals Problem。
二人の将軍の問題ですね。
これは信頼できない通信路、ネットワークの通信路を介して、
これ二人の将軍というのはアナロジーなんですけど、
二人の将軍が同時にターゲットとなるお城でも何でもエリアでもいいんですけど、攻撃するぞというシチュエーションをイメージしたときに、
そこでその二人の将軍が合意形成がいかに困難であるかというのを示している例になってますね。
これはそのネットワークの信頼性の問題に焦点を当てているキーワードでした。
もう一つがFLP Impossibilityということで、これは何かというと、
非同期システムにおいて障害が発生する可能性がある場合に、
限られた時間の中でコンセンサス、合意を取ることが不可能であるという理論的な限界を示しているものですね。
あとは失敗するモデルというかFailure Modelsにもついて触れられていました。
これはシステムがどのような障害、失敗パターンを起こす可能性があるかを分類するもので、
これらを知識として知っておくことで対策を考える手助けになるという話ですね。
SREとかDevOpsとか、もしくはデータベース開発をしている人にとっては、
結構割と知っていることも多いかもしれないんですけども、
バックエンドエンジニアの方とかフロントエンジニアの方から見るんだったら、
分散システムの課題
このFailure Modelsのリストを理解するというのは、いいスターティングポイントになるんじゃないかなと思います。
ということで、BookClubで盛り上がった観点について紹介しようかなと思います。
今回のBookClubでも非常に活発な議論が交わされました。
特に盛り上がったのはですね、Exactly Once Delivery、
つまり一度だけ配信するという時の実装の難しさについてでした。
分散システムでこれを完全に実現するのは非常に難しいとされています。
取り得る方法としては、例えばシステムをベキッドにするとか、
あとはつまり同じ操作を複数回実行しても結果が変わらないようにするということなんですけど、
もしくはログとかデータの受け取り側でディルプリケーション、
重複を排除することで実際一度だけ処理されるようにするというアプローチがあります。
ほとんどの現実の世界のシステムでは、
送信側が確認応答、アクノレッジメントを受け取るまで再試行を続ける
At Least Once Deliveryセマンティックスですね。
だから最低1回は送るよっていうセマンティックスを採用している点がほとんどないんじゃないかなというのを改めて確認できました。
我々が普段使っているシステムは実は完璧なExactly Once Deliveryというわけではないのだなと気づかされますね。
コンセンサスアルゴリズムの理解
それからメッセージ、ネットワークを通して送信されるログとかメッセージの準序保証、オーダーのギャラリティですね。
準序保証についても話が呼びました。
例えばシーケンス番号を管理して順番通りに処理して、次の番号よりも先に届いた場合はバッファリングしておくとか、
既に処理されていたら捨てるみたいなシンプルな説明だったと記憶しています。
イベントソーシングのようなシステムを作るときにもこの準序保証というのは重要な概念になってきますよね。
それからバックエンドエンジニアにとってはおなじみのバックオフとかジターという概念についても触れられましたね。
分散すればするほど遅くなるという現実に対してどのようにクライアント側でリトライ戦略を立てるのかという話でした。
これに付随してThundering Hard Problemの説明などもしました。
個人的に今回の章のハイライトとも言えるのが、
Two Generals ProblemとByzantine General Problemの違いについての議論でした。
本章で紹介されているのはTwo Generals Problemなんですけど、
本章ですね。
Byzantine General Problemというのもありますと、
まずTGPと呼ばれるTwo Generals Problemというのは先ほどもちょっと説明しましたけど、
信頼できないネットワーク通信チャンネルにおけるメッセージの損失とか遅延が主な課題であって、
二人の将軍の間では完璧な合意を達成することは理論的に不可能ですよということを証明した理論です。
一方、ジェネラルという観点でちょっと似ているのでよく聞く。
しかも分散界隈でよく聞くんですけど、
そのByzantine General Problem、BGPと呼ばれるのは、
このちょっと違って、
悪意のあるあるいは故障したアクターですね、
これビザンチン障害というんですけど、
これが存在する環境での合意形成が課題となります。
なぜこのビザンチンというのかというのは、
これを発明したランポート博士というめちゃくちゃ有名な方が書いた、
分散システムにも過大な貢献をしたすごい優秀な博士がいたんですけども、
彼がアナロジーを使って説明するのが上手で、
このペーパーにもそのビザンチンを攻める時の将軍たちのアナロジーを使って表現された感じですね。
この裏切り者と呼ばれる、複数の将軍の中にもし裏切り者がいたらどうするか、
もし裏切り者がいたらビザンチンの将軍たちの間で城を攻めるかどうかの合意を形成できるか、
について書かれた論文なんですね。
ということでビザンチン将軍の話をすると、
もう少しここら辺のコンセンスアルゴリズムの難しさを話したくなってくるんですけれども、
また脱線してきた気がするんですが、
この収録は本書の丸写しというよりは、
本にインスピレーションを受けつつ周辺コンセプトを紹介していくということなので、
また脱線してしまうんですけどお付き合いくださいということで、
このビザンチン将軍問題、そしてこれを解決するコンセンスアルゴリズムの難しさを理解するために、
また別のアナロジーを紹介しようと思います。
僕が自分のkenwagatsuma.comのブログで書いている、過去に書いたブログがあるんですけれども、
コンセンサスアルゴリズムを理解するときに、
人狼ゲームって皆さんご存知ですかね。
人狼ゲームというのはボードゲームとか、
複数人で遊ぶゲームの一種なんですけど、
その人狼ゲームのアナロジーを使って合意形成アルゴリズムを紹介したという、
めちゃくちゃ時間をかけて書いたわりには全然読まれないブログがありまして、
ちょっとこれを機にぜひ紹介したいと思うんですけど、
皆さん人狼ゲームはプレイしたことありますかね。
これはどういうゲームかというと、
村人と人狼チームというのに分かれて、
昼と夜のフェーズがあるんですね。
誰が人狼かというのが分からないんですよ。
村人側と人狼側のそれぞれのゴールというのがあって、
村人側は生き残ること、
人狼チームは村人を襲うこと。
心理戦のパーティーゲームの一つでして、
昼のフェーズではみんなで議論して人狼を特定して、
夜は人狼が村人を襲うというフェーズになっています。
この昼のフェーズで人狼同士に議論するとき、
誰が人狼か分からない。
これは要するにビザンチン問題でいうと裏切り者に当たるわけですね。
この人狼ゲームを分散システムにおける合意形成に例えると、
非常に面白い洞察が得られます。
まず、ゲームの参加者たちはそれぞれが独立したノードだと考えてみましょう。
そして村人たちは正常なノード、
人狼は悪意のあるあるいは故障したノード、
つまり裏切り者の役割を果たすとみなせます。
人狼チームは互いに誰が人狼かを知っていますが、
村人は誰が味方か分かりません。
この情報の非対称性が悪用されて、
人狼チームは村人たちの間に混乱を生み出すことができるんですね。
ヒルの議論フェーズは繰り返しになりますが、
まさに分散システムにおけるリーダー選出とか、
状態の共有プロセスに似ています。
村人たちは議論を通じて人狼を推測しようとするんですけれども、
人狼というのは自分が村人であるかのように嘘をつき、
無実の村人を吊るし上げようとしてしまうんですね。
つまり正常なノードが悪意のなるノードから偽の情報を受け取って、
それが全体の合意形成を阻害する可能性があるわけです。
そして夜の投票フェーズでは意思決定が行われます。
合意形成をみんなでトライしようとするわけですね。
多数決で誰かを追放するんですけれども、
もし人狼が過半数を占めてしまえば、
彼らは一方的に村人を排除できるようになりますよね。
これは分散システムで言えば過半数のノードが悪意を持つ、
あるいは故障してしまう51%攻撃のような状況に例えられます。
この状態に陥るとシステムは正常な合意を形成できなくなり、
全体としてその機能が失われてしまいます。
このアナロジーで人狼ゲームのルールを考えてみるとめちゃくちゃ面白くてですね。
人狼ゲームというのは理論的には最低3人からプレイできることが決められていて、
そして面白くなるたびには5人以上が推奨されているんですね。
5人というのはディストリビューティーとデータベースを管理している人からしたら
ちょっと聞き馴染みのあるマジックナンバーだと思うんですけど、
コンセンサスアルゴリズムにおける最低限必要なノード数とか、
推奨されるノード数に酷似していますよね。
例えば信頼性を確保するためには最低3ノード必要ですし、
対障害性を高めるために5ノードが推奨されるという、
いろんなディストリビューティーとデータベースのドキュメンテーションの
オペレーションページとかでも推奨されているこのマジックナンバーは
この人狼ゲームのアナロジーでもより直感的に理解できるのではないでしょうか。
このように人狼ゲームはですね、分散システムにおける裏切り者の存在が
合意形成にいかに大きな影響を与えるか、
そしてシステムがどのように多数決原理や情報交換を通じて健全性を保とうとするか
人狼ゲームと分散システム
という複雑な概念を楽しくかつ具体的にイメージさせてくれる
良いアナロジーだと思います。
我々が普段意識しないようなデータベースの裏側で動いている
コンセンサスアルゴリズムを、実はこういった複雑な課題を解決するために
日々奮闘しているわけですね。
ということで、壮大に達成してしまったんですけれども、
この人狼ゲームを通じて分散システムを理解するというのは
なかなか面白いんじゃないでしょうか。
ということで、次回はチャプター9、フェイラーディテクションに入っていきます。
キーワードとしては、ハートビートとかゴシップ、フェイラーディテクションなどがあります。
分散システムの醍醐味が垣間見える興味深い章となるのではないでしょうか。
ということで、引き続き読んでいきましょう。
チャプター8の振り返りは以上にしようと思います。
今回はチャプター8、Distributed Systems Introduction and Overviewについて振り返りました。
分散システムの基本的な概念とその複雑さ、
そしてそれらにどう対処していくのかという導入部分だったんですけれども、
非常に多くの学びがあったのではないでしょうか。
ということで、次はチャプター9の振り返り収録でお会いしましょう。
それでは皆さん、Have a nice day.
26:33

コメント

スクロール