5 章 レプリケーション
レプリケーションの目的は
- データを地理的にユーザの近くで保持しておくことでレイテンシを下げる
- 一部に障害があってもシステムが動作し続け可用性を高める
- 読み取りのクエリを処理するマシン数をスケールアウトし、スループットを高める
リーダーとフォロワー
レプリカとはデータベースのコピーを保存する各ノードのこと。全てのレプリカにはデータベースのコピーが行きわたっている必要がある。そのための仕組みがリーダーとフォロワー。
- レプリカの一つはリーダーと呼ばれる。書き込みリクエストは必ずリーダーに送られる。リーダーは新しいデータをローカルに書き込む。
- 他のレプリカをフォロワーと呼ぶ。リーダーはローカルに書き込むとその変更データを各フォロワーに送信する。各フォロワーは受け取ったデータを順番にローカルに書き込む。
- クライアントがデータの読み取りをしたい場合は、どのレプリカから行っても良い。ただし、書き込みはリーダーのみ行える。
Cosmos の物理パーティションは最低でも 1 つのリーダーと 3 つのフォロワーにより構成されている。コンテナがどれほど小さくでも、物理パーティション一つに付き最低でも 4 つのレプリカを持つ。そのうち 1 つがリーダーで、残り 3 つがフォロワーとなる。このレプリカのまとまりをレプリカセットと呼んだりする。
5 つの一貫性レベルがあるが、あれはレプリカセット内での話か?もちろんリージョン跨いで分散されるものだろうけど。
Cosmos DB は同一論理パーティションであればトランザクション処理が行えるが、それって
- 論理パーティションキーが同じであれば、同じ物理パーティションに所属する
- ローカルストレージへのディスクIOの単位がトランザクション処理で受け付けるサイズ上限になりそう?
- 同じ物理パーティション内であればローカルストレージに書き込むだけになる
- 物理パーティションが異なれば、別マシンで処理する可能性があり、ネットワークが絡むと確実に処理が成功するとは限らない
って理由なのじゃなかろうか?論理パーティションキーから物理パーティションを逆引きも出来るから異なる論理パーティションでも可能かもしれないけど、SDK 側でそのチェックやると実行時エラー置きまくって使い勝手悪そう...。アプリ側で考慮すると複雑化するし、そもそも意識する必要ないものだし?
リーダーは変更データを各フォロワー向けに送信するとあったが、これは Change Feed の仕組みと関係あったりするのかな?この辺の解像度を上げるのは別でやる必要がある。
SQL Server には Always On availability group
というものがある。この辺は Hyperscale と関係してんのかなぁ。これも別でやる。
レプリケーションは同期でやるのか非同期でやるのか問題。同期でやるメリットは、常にリーダーとフォロワーの間で読み取れるデータが一致する事。一貫性が保たれるというわけですな。非同期でやる場合はフォロワーが壊れてもリーダーへの書き込みは成功する事。可用性が高まるという事ですな。CAP 定理の話だね。
この本では一つのフォロワーを同期的に更新し、残りのフォロワーを非同期にする方法が紹介されていた。同期的に更新していたフォロワーが壊れると、非同期でやっていたフォロワーをどれか一つ同期的に変更する。これで一貫性と可用性のバランスを取る。この方法は準同期型 (semi-synschronous)
って呼ばれてるらしい。
Azure Storage はチェーンレプリケーションが採用されている。これは同期型の発展形。
https://sigops.org/s/conferences/sosp/2011/current/2011-Cascais/printable/11-calder.pdf
http://www.umbrant.com.s3-website-us-west-1.amazonaws.com/blog/2016/windows_azure_storage.html
チェーンレプリケーションっていうのは、書き込みリクエストと読み取りリクエストを受けつけるノードを分け、レスポンスを返すノードを一つにするもの。書き込みはHEADから始まり、差分を全ノードに順番に送る。TAILがその差分を受け付けると、そのままレスポンスを返す。同期的なレプリケーションは書き込みリクエストを受け付けたノードが、レプリケーション先のノードからACKが返ってくるのを待機している。チェーンレプリケーションは ACKは非同期で返すからスループットが良いって事なのかな?
フォロワーのセットアップはある時点のスナップショットの適応と、それ以降の変更の要求により行う。だいたいはストレージの機能として用意されてるんじゃないか?増分バックアップとかに似た考え方かも。ストレージ自体を別者に置き換えるとかなら、スナップショットを適応して W write をするとかあるなぁ。
ノード障害への対応
- フォロワーの障害: キャッチアップリカバリ
- フォロワーはローカルにリーダーからの変更通知の処理結果と、どこまで処理したのかの情報を持っている。それ以降の情報を障害からの復旧時にリーダーに要求すればよい。
- リーダーの障害: ファイルオーバー