書いたのに、古い値が見える
分散システムの一貫性とは、書き込みのあとに、読む人がどの値を見るかについての約束です。写しがあるシステムでは、書いた直後に読んでも、古い値が返ることがあります。
チケット販売で考えましょう。買い物かごでは残り3枚なのに、別の画面は4枚と表示している。この食い違いは、なぜ起きるのでしょうか。
このレッスンのゴール
メモ
書き込みのあとで読み手が何を見るかと、そこにあるトレードオフを説明できます。
キーワード
| ことば | いみ |
|---|---|
| 一貫性 | 書いたあとに、読む人が見る値についての約束 |
| 強い一貫性 | 書いたあとは、誰が読んでも新しい値を見ること |
| 結果整合性 | 書くのをやめれば、いつか全部の写しが同じになること |
| 古い読み取り | 写しがまだ更新されず、古い値を読んでしまうこと |
| トレードオフ | 何かを得ると、別の何かを手放すこと |
学生が入力するセルは、このプレビューでは空白です。
強い一貫性は、新しい値だけを見せる
強い一貫性では、書き込みが成功したら、そのあとの読み取りは、誰がどの機械で読んでも新しい値を返します。
そのために、書き込みは、全部の写しに届くまで「成功」と答えません。ですから、書き込みは遅くなります。写しの1台に届かないときは、書き込みを断ることもあります。
小さなクライアント v を作る
v() ( printf '%s\r\n' "$*" | nc -w 1 valkey 6379 )ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
チケットの残りを4枚にする
v SET ds:stock 4ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
1枚売れたので3枚にする
v SET ds:stock 3ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
すぐに読み直す
v GET ds:stockここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
1台の写しの確認を、0.1秒待つ
v WAIT 1 100ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
1台なら、いつも新しい値が返る
ラボのValkeyは1台なので、書いた直後に読むと、必ず新しい値が返ります。写しがないので、古い値は存在しません。
WAIT は、写しが何台、書き込みを受け取ったかを尋ねます。ラボには写しがないので、答えは0台です。
結果整合性は、速さを優先する
結果整合性では、書き込みはプライマリが受け取った時点で成功します。写しへは、あとから届きます。
書くのをやめれば、いつか全部の写しが同じ値になります。ただし、それまでの間は、読む場所によって答えが違います。これが古い読み取りです。
例: 古い値が見える時間
| 時刻 | 操作 | プライマリ | レプリカ |
|---|---|---|---|
| 1 | 残り4枚の状態 | 4 | 4 |
| 2 | 1枚売れて、3に書き換える | 3 | 4 |
| 3 | レプリカから読む | 3 | 4(古い値を返す) |
| 4 | 変更がレプリカに届く | 3 | 3 |
| 5 | レプリカから読む | 3 | 3(新しい値を返す) |
学生が入力するセルは、このプレビューでは空白です。
古い値が返る様子
# プライマリの値を変えます。レプリカには、まだ届いていません。
primary = {"stock": 4}
replica = {"stock": 4}
primary["stock"] = 3
print("すぐにレプリカを読む:", replica["stock"])
replica["stock"] = primary["stock"]
print("変更が届いたあと:", replica["stock"])
# 最初の 4 を 10 に変えて、もう一度実行してみましょう。
よくある間違い
注意
結果整合性は、データがいつか壊れるという意味だと考えがちです。書くのをやめれば、全部の写しが同じ値になるという意味です。ただし、それまでの間は、読む場所によって答えが違います。