前回からつづいてYugabyteDBのドキュメントを読んでいきます。
前回はArchitecture > Core functions > Table Creationを読みました。 今回はArchitecture > Core functions > Write I/O pathを読みます。
ドキュメントのバージョンは最新のv2.19 previewです。 また画像は同ドキュメントより引用しています。
Write I/O path
Write I/O pathはYQLレイヤーで処理され、タブレットリーダーによってレプリケーションの準備が行なわれる シングルキーでの書き込みとして例示することが出来る。
アトミックなアップデートを共なう複数キーでの分散トランザクションなど複雑なケースについては 分散トランザクションに記載する。
Write operation processing by YQL layer
ユーザーが発行したYQLクエリレイヤに作用するライトリクエストはポートから適切なAPI(YQLまたはYCQL)を経由して行なわれる。 このユーザーリクエストはYQLレイヤで内部キーに変換される。 シャーディングで説明するように、 それぞれのキーは一つのタブレットが所有する。 どのタブレットがキーを所有するか特定するために、YQLレイヤはYB-MasterにRPC1呼び出しを実行する。 そのレスポンスは将来の利用のためにキャッシュされる。
YugabyteDBはタブレットの場所をキャッシュし直接参照することでネットワークホップを減らすことで、YQLレイヤが直接適切なYB-TServerにホストされるタブレットリーダーにリクエストを送信することが出来るスマートクライアントを持つ。 YQLレイヤがローカルノードにタブレットリーダーを見つけた場合、RPCはローカルファンクションコールになりリクエストをシリアライズとデシリアライズしてネットワーク越しに送信する時間を節約することが出来る。
その後YQLレイヤはタブレットリーダーをホストするYB-TServerへの書き込みを発行する。 この書き込みはキーを所有するRaftグループのタブレットリーダーによって処理される。
Preparation of the operation for replication by tablet leader
下記の図はタブレットリーダーがレプリケーションを実行する処理を説明している。
タブレットのRaft Groupリーダーは以下の処理を実行する。
- 現在実行されている処理が現在のスキーマに対応しているかを判別する
- キーに対してローカルin-memoryロックマネージャーを利用してロックを取得する。このロック機構はフォロワーには存在しない
- 必要であればデータを読み込む(read-modify-writeや条件付きアップデート命令など)
- DocDBに書き込まれる変更のバッチを準備する。この書き込みバッチは殆ど最終的にRocksDBに書き込まれるKey-Valueペアに近く、それぞれのキーの末尾に最終的なhybrid timestampが添えられていないだけである
Raft replication of the write operation
書き込みのRaftレプリケーション処理の流れは以下のように説明することが出来る。
- リーダーがバッチをRaft logにアペンドし、書き込みのためのhybrid timestampを選択する
- Raftを利用しデータをピアーに複製する
- 成功したRaft replicationのデータをローカルのDocDBに反映する
- ユーザーに成功を返す
フォロワータブレットはRaftを利用したデータの複製を受けつけ、コミットされた事が分ったタイミングでその複製をローカルのDocDBに反映する。 リーダーは以下のようにコミットポイントに於ける後続のRPCリクエストの進行を進める。
- 書き込みバッチを含むRaftエントリーは過半数以上のタブレットRaft Groupピアーに複製される
- Raftのサブシステムから"Replication Successful"のコールバックを取得したあと、リーダーはローカルのDocDBにバッチの書き込みを適用する
- リーダーからの次の更新でエントリーがコミットされたことがフォロワーに通知され、フォロワーはそれぞれのRocksDBインスタンスにバッチの書き込みを適用する。
Response to the client
Information Pending2
Examples
k
とv
という値をK
という行とV
という行をもつテーブルT1
に挿入する例について考える3。
この例ではユーザーアプリケーションがランダムなYugabyteDBサーバにWriteクエリを送信し、そのサーバがリクエストを適切にルーティングすると仮定して簡略化している。
特にYCQLではYugabyteDB Smart Clientを使うことで、余分なネットワークホップを避けることが出来る。