Slide 1

Slide 1 text

How COMMIT works in CockroachDB \ コンニチワ /

Slide 2

Slide 2 text

● Name: Takanori Yokoyama ○ @kota2and3kan (Twitter, GitHub) ● Job: Technical Support ● Like: DB ○ PostgreSQL, CockroachDB ● Dislike: Real Cockroach @kota2and3kan こたつ&&みかん Who am I.

Slide 3

Slide 3 text

※Note※ ちょっと自信が無いとこもあります! 間違ってたらごめんさない!!! \ ユルシテ /

Slide 4

Slide 4 text

目次 ● CockroachDB についてざっくり概要 ● COMMIT / ABORT (Write) の動作 ● Read の動作 ● Parallel Commits ● 話せなかったこと ● まとめ ● おまけ

Slide 5

Slide 5 text

CockroachDB についてざっくり概要 \ ガイヨウ /

Slide 6

Slide 6 text

CockroachDB 概要 ● 分散 SQL データベース。いわゆる NewSQL。 ● Spanner と F1 にインスパイアされている。 ● 公式曰く CAP でいうと CP システム。 ○ https://www.cockroachlabs.com/docs/stable/frequently-asked-questions.html#how-is-cockroachdb-both-highly -available-and-strongly-consistent ○ (Linearizability は満たしてないので厳密にいうと “P システム” ?) ● コンセンサスアルゴリズムには Raft を使用。 ● Storage Engine に独自開発の KVS (Pebble) を使用。 ○ https://github.com/cockroachdb/pebble ○ 以前は RocksDB を使っていた。今も後方互換として使える。 ● Isolation Level : Serializable ● Consistency Level : No Stale Reads ○ https://www.cockroachlabs.com/blog/consistency-model/

Slide 7

Slide 7 text

全てのノードで Read / Write のクエリを処理可能 Load Balancer Service (k8s) etc... Read / Write

Slide 8

Slide 8 text

全てのノードで Read / Write のクエリを処理可能 Load Balancer Service (k8s) etc... Read / Write Scale OUT / IN も可能。

Slide 9

Slide 9 text

CockroachDB についてざっくり概要 格納されるデータ (Key-Value) の構造 \ キーバリュー /

Slide 10

Slide 10 text

Table と Key-Value id c1 c2 c3 1 foo bar baz 2 hoge fuga piyo 3 (・ω・´) (´・ω・`) m9(^Д^) key value /Table/54/1/1/0/1615095374.173379261,0 c1: foo, c2: bar, c3: baz /Table/54/1/2/0/1615095392.837630582,0 c1: hoge, c2: fuga, c3:piyo /Table/54/1/3/0/1615095596.484809926,0 c1: (・ω・´), c2: (´・ω・`), c3: m9(^Д^) test ※ id -> Primary Key ・Key-Value 形式に変換。 ・Key で Sort。 ・最近はデフォルトだと 1 record = 1 KV。 ・Key は以下の形式で変換される。 ・Key に Timestamp が含まれている。 /Table/Table ID/Primary Key ID/Value of PK/Column Family/Timestamp https://github.com/cockroachdb/cockroach/blob/master/docs/tech-notes/encoding.md

Slide 11

Slide 11 text

Table と Key-Value (補足) id c1 c2 c3 1 foo bar baz 2 hoge fuga piyo 3 (・ω・´) (´・ω・`) m9(^Д^) key value /Table/54/1/1/0/1615095374.173379261,0 c1: foo, c2: bar, c3: baz /Table/54/1/2/0/1615095392.837630582,0 c1: hoge, c2: fuga, c3:piyo /Table/54/1/3/0/1615095596.484809926,0 c1: (・ω・´), c2: (´・ω・`), c3: m9(^Д^) test ※ id -> Primary Key key value 0xBE898988001669F8AF87FB1ABD09 0x4CF924910A2603666F6F1603626172160362617A 0xBE898A88001669F8B3E074FA7609 0x65EEC34A0A2604686F676516046675676116047069796F 0xBE898B88001669F8E34AC654C609 0xC11CE7CF0A260C28E383BBCF89E383BBC2B429160D28C2B4E383BBCF89E3 83BB602916086D39285ED0945E29 ※実際は Byte 形式で格納される。

Slide 12

Slide 12 text

Keyspace test Monolithic & Sorted by key tbl1 tbl2 key value /Table/54/1/1/0/1615095374.173379261,0 c1: foo, c2: bar, c3: baz /Table/54/1/2/0/1615095392.837630582,0 c1: hoge, c2: fuga, c3:piyo /Table/54/1/3/0/1615095596.484809926,0 c1: (・ω・´), c2: (´・ω・`), c3: m9(^Д^) Key-Value と Keyspace Key-Value 形式に変換された各 Table は、 Key で Sort された Keyspace (論理的に  1つの大きな塊) に map される。

Slide 13

Slide 13 text

Keyspace と Range Range1 Range2 Range3 ・ ・ ・ Range N 512MB 512MB 512MB Keyspace ・いい感じに分割。 ・デフォルト 512MB。

Slide 14

Slide 14 text

Range と Node Range1 Range2 Range3 ・いい感じに分散。

Slide 15

Slide 15 text

Range と Node Range2 Range1 Range3 Range1 Range2 Range3

Slide 16

Slide 16 text

Range と Node Range2 Range1 Range3 Node 障害 = データ消失

Slide 17

Slide 17 text

Range と Replica Range2 Range1 Range3 ● Range を複製 (Replica)。 ● デフォルト 3つ。 ● Replica をいい感じ分散。 ● 各 Replica は Raft を使って複製する。 Range1 Range1 Range2 Range2 Range3 Range3

Slide 18

Slide 18 text

Range と Replica Range2 Range1 Range3 適当に Read / Write = データ不整合 Range1 Range1 Range2 Range2 Range3 Range3

Slide 19

Slide 19 text

Replica と Leaseholder Range1 Range2 Range3 Range1 Range2 Range3 Range1 Range2 Range3 lease lease lease ● Replica の 1つが lease を持つ。 ● lease を持つ Range をLeaseholder と呼 ぶ。 ● Read / Write は全て Leaseholder で処 理。 ● 基本 Leaseholder = “Raft Leader” にな る。

Slide 20

Slide 20 text

5匹の場合 Range1 Range2 Range3 Range1 Range2 Range3 Range1 Range2 Range3 lease lease lease ● Node が増える と、いい感じに分 散される。

Slide 21

Slide 21 text

Range Group Range1 Range2 Range3 Range1 Range2 Range3 Range1 Range2 Range3 lease lease lease Raft Group 1 Raft Group 2 Raft Group 3 ● Range 毎に Raft Group を作成。

Slide 22

Slide 22 text

CockroachDB についてざっくり概要 SQL を誰が処理するか \ クエリ /

Slide 23

Slide 23 text

Gateway Node (Coordinator) ● クエリを受け取った Node は “Gateway Node” と呼ばれる。 ○ いわゆる “コーディネーター” Node。 ● Gateway Node が Tx を管理する。 ○ Tx 内の各 SQL は Gateway Node 経由で各 Node にルーティングされる。 ● 各 Node で処理されたデータ (SQL の結果) は、Gateway Node に集約され、Gateway Node から Client に SQL の結果を返す。 SQL

Slide 24

Slide 24 text

Range1 Range2 Range3 lease ● Gateway Node 内に Leaseholder が有る。 ○ 自分で処理。 ● Gateway Node 内に Leaseholder が無い。 ○ Leaseholder を持つ Node にクエリをルーティ ング。 ● つまり Tx 内の各 SQL は Raft Leader 経由で Read / Write を実行する。 ○ Raft Leader を持つ Node に SQL がルーティン グされる。 Gateway Node の動作

Slide 25

Slide 25 text

Write Query その1 Write lease lease lease ● Gateway Node == Leaseholder

Slide 26

Slide 26 text

Write Write Query その2 lease lease lease ● Gateway Node != Leaseholder

Slide 27

Slide 27 text

● 時間が足りないので割愛。 ● もう少し細かい説明は以下参照。 ○ https://speakerdeck.com/kota2and3kan/20190701-what-is-cockroachdb?slide=48 Gateway Node の動作

Slide 28

Slide 28 text

COMMIT / ABORT (Write) の動作 \ コミット /

Slide 29

Slide 29 text

用語概要 ● Transaction Record ○ https://github.com/cockroachdb/cockroach/blob/v20.2.5/pkg/roachpb/data.pb.go#L940 ● Write Intent ○ https://github.com/cockroachdb/cockroach/blob/v20.2.5/pkg/roachpb/data.pb.go#L985 ○ https://github.com/cockroachdb/cockroach/blob/v20.2.5/pkg/storage/enginepb/mvcc3.pb.go#L 31 ● Transaction Liveness Threshold ○ https://github.com/cockroachdb/cockroach/blob/v20.2.5/pkg/kv/kvserver/txnwait/queue.go#L46

Slide 30

Slide 30 text

用語概要 (Transaction Record) ● Transaction の状態を管理する。 ● Tx 内で最初に Write された key と同じ Range に書き込まれる。 ● 以下の State がある。 ○ PENDING ■ Tx は処理中。 ○ COMMITTED ■ Tx は COMMIT 済み。 ○ STAGING ■ Tx は Parallel Commits で処理中。 ○ ABORTED ■ Tx は ABORT 済み。 ○ (MISSING) ■ Transaction Record そのものが無い。

Slide 31

Slide 31 text

用語概要 (Write Intent) ● Transaction の状態 (COMMIT / ABORT) が確定していないレコード (KV) に付けられる印。 ● 以下のような情報を持っている。 ○ 関連する (当該レコードを Write した) Tx の ID。 ○ Write Intent が書き込まれた時間。

Slide 32

Slide 32 text

用語概要 (Transaction Liveness Threshold) ● Transaction の生死 (Tx を管理している Node の生死) を判断するための 閾値 (死んだと判断するまでの時間)。 ○ Gateway Node での障害発生有無を確認する場合等に使われる。 ○ 文字通り、そのまんまの感じのやつ。

Slide 33

Slide 33 text

COMMIT の仕組み Range : Set of KV date (512BM) Tx1 (timestamp t1) BEGIN; Write (key1, x1); COMMIT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0

Slide 34

Slide 34 text

Tx 開始 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); COMMIT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0

Slide 35

Slide 35 text

key1 を更新 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); COMMIT; Write (UPDATE) は Inplace   Update ではなく、新しい   Timestamp で追記する。 この時 COMMIT / ABORT  が 確定していない KV には   “write intent” という印が付 け られる。 key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1)

Slide 36

Slide 36 text

Transaction Record (PENDING) を作成 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); COMMIT; Tx の状態を管理するための ”Transaction Record” が他の KV データ同様に書き込まれる。 各 “write intent” は、対応する Transaction Record を特定する 情報 (Tx の ID) を持っている。 key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1) Tx1’s “Transaction Record” ------------------------------------ State: PENDING

Slide 37

Slide 37 text

Transaction Record の State を COMMIT に更新 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); COMMIT; COMMIT を実行すると、  Transaction Record の値が COMMITTED に変更される。 このタイミングで、クライアントに COMMIT 完了を返す。 key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1) Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED

Slide 38

Slide 38 text

“write intent” を削除 (COMMIT とは非同期で実施) Range : Set of KV date (512BM) BEGIN; Write (key1, x1); COMMIT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED COMMIT 完了後、非同期で “write intent” が削除され、通常 の KV と同じ状態になる。

Slide 39

Slide 39 text

Tx Record を削除 (COMMIT とは非同期で実施) Range : Set of KV date (512BM) BEGIN; Write (key1, x1); COMMIT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED Tx に関連する全ての “write intent” が削除された後、 Transaction Record が非同期 で削除される。

Slide 40

Slide 40 text

ABORT の仕組み Range : Set of KV date (512BM) Tx1 (timestamp t1) BEGIN; Write (key1, x1); ABORT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0

Slide 41

Slide 41 text

Tx 開始 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); ABORT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0

Slide 42

Slide 42 text

key1 を更新 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); ABORT; Write (UPDATE) は Inplace   Update ではなく、新しい   Timestamp で追記する。 この時 COMMIT / ABORT  が 確定していない KV には   “write intent” という印が付 け られる。 key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1)

Slide 43

Slide 43 text

Transaction Record (PENDING) を作成 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); ABORT; Tx の状態を管理するための ”Transaction Record” が他の KV データ同様に書き込まれる。 各 “write intent” は、対応する Transaction Record を特定する 情報 (Tx の ID) を持っている。 key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1) Tx1’s “Transaction Record” ------------------------------------ State: PENDING

Slide 44

Slide 44 text

Transaction Record の State を ABORT に更新 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); ABORT; ABORT を実行すると、  Transaction Record の値が ABORTED に変更される。 key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1) Tx1’s “Transaction Record” ------------------------------------ State: ABORTED

Slide 45

Slide 45 text

“write intent” を削除 (ABORT とは非同期で実施) Range : Set of KV date (512BM) BEGIN; Write (key1, x1); ABORT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 key1 (t1): x1 (intent:Tx1) Tx1’s “Transaction Record” ------------------------------------ State: ABORTED ABORT 後、非同期で ABORT された key が削除される。

Slide 46

Slide 46 text

Tx Record を削除 (ABORT とは非同期で実施) Range : Set of KV date (512BM) BEGIN; Write (key1, x1); ABORT; key1 (t0): x0 key2 (t0): y0 key3 (t0): z0 Tx1’s “Transaction Record” ------------------------------------ State: ABORTED Tx に関連する全ての key が削 除された後、Transaction Record が非同期で削除される。

Slide 47

Slide 47 text

Read の動作 \ リード /

Slide 48

Slide 48 text

Read Tx はどの値を読み込むのか? Range : Set of KV date (512BM) Tx1 (timestamp t1) BEGIN; Write (key1, x1); COMMIT / ABORT; Tx2 (timestamp t2) Read (key1); key1 (t0): x0

Slide 49

Slide 49 text

Read Tx は Timestamp を見て読み込む値を決める Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); Tx1’s “Transaction Record” ------------------------------------ State: PENDING Tx2 (t2) Read (key1); -> x0 t0 < t2 < t1 だった場合は、t0 の値 (x0) を 読む。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0

Slide 50

Slide 50 text

Read Tx は Timestamp を見て読み込む値を決める Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); Tx1’s “Transaction Record” ------------------------------------ State: PENDING Tx2 (t2) Read (key1); -> x1 (intent:Tx1) t0 < t1 < t2 だった場合は、t1 の値 (x1) を 読む。(x1 は “write intent” なのでこの時 点で COMMIT / ABORT は不明) key1 (t1): x1 (intent:Tx1) key1 (t0): x0

Slide 51

Slide 51 text

Read した値が “write intent” だった場合 Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); Tx1’s “Transaction Record” ------------------------------------ State: PENDING Read した値が “write intent” だった場合、 Tx Record の値を確認する。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 Tx2 (t2) Read (key1); -> x1 (intent:Tx1)

Slide 52

Slide 52 text

Read した値が “write intent” だった場合 (COMMIT) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); COMMIT; Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED Tx Record の値が COMMITTED だった 場合は COMMIT 済みなので、そのまま x1 を Read する。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 Tx2 (t2) Read (key1); -> x1

Slide 53

Slide 53 text

Read した値が “write intent” だった場合 (ABORT) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); ABORT; Tx1’s “Transaction Record” ------------------------------------ State: ABORTED Tx Record の値が ABORTED だった場合 は Tx1 の更新が無かったことになるので、 x0 を Read する。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 Tx2 (t2) Read (key1); -> x0

Slide 54

Slide 54 text

Read した値が “write intent” だった場合 (PENDING) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); … ... Tx1’s “Transaction Record” ------------------------------------ State: PENDING Tx Record の値が PENDING だった場合 は状態 (COMMIT / ABORT) が確定して いないので、Tx1 の完了を待つ。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 Tx2 (t2) Read (key1); -> wait...

Slide 55

Slide 55 text

Read した値が “write intent” だった場合 (MISSING) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); 特定のタイミング (Tx 処理中) や Gateway Node の障害等に起因して、Tx Record が 存在しない場合もある。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 Tx2 (t2) Read (key1); -> ??? Tx1’s “Transaction Record” ------------------------------------ MISSING

Slide 56

Slide 56 text

Read した値が “write intent” だった場合 (MISSING) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); Tx Record が無い場合は “write intent” の Timestamp が “Transaction Liveness Threshold” の範囲内か否かをチェックす る。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 Tx2 (t2) Read (key1); -> ??? 無い...? Tx1’s “Transaction Record” ------------------------------------ MISSING

Slide 57

Slide 57 text

Read の動作 補足 (Transaction Liveness Threshold) \ ダッセンスルヨ /

Slide 58

Slide 58 text

  補足 (Transaction Liveness Threshold) Node 1 Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: PENDING key1 (t0): x0 key1 (t1): x1 (intent:Tx1) SQL を受け取った Gateway Node (いわゆるコーディネーター) が Tx を管理している。 Manage Create Write \ カンリ /

Slide 59

Slide 59 text

  補足 (Transaction Liveness Threshold) Node 1 Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: PENDING key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Tx1 の途中で Node 障害が発生すると、その Node が管理していた Tx1 は ABORT することになるが、Range の中に Transaction Record が PENDING のまま残ってしまう。 ~

Slide 60

Slide 60 text

  補足 (Transaction Liveness Threshold) Node 1 Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: PENDING key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Range の中に Transaction Record が PENDING のまま残ってい ると、他の Tx2 が Tx1 の状態を判断できず、いつまでも Tx1 の状 態が確定 (COMMIT or ABORT) するのを待ってしまう。 Tx2 (t2) Read (key1); -> wait... Wait forever... Read \ マダー? / Node 2

Slide 61

Slide 61 text

  補足 (Transaction Liveness Threshold) Node 1 TxnCoordSender Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: PENDING key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Transaction Record の残存を防ぐため Gateway Node 内の TxnCoordSender が Transaction Record に対して定期的に Heartbeat を実施している。多分デフォルト 1秒間隔。 https://github.com/cockroachdb/cockroach/blob/v20.2.5/pkg/base/constants.go#L27 Heartbeat \ イキテルヨ /

Slide 62

Slide 62 text

  補足 (Transaction Liveness Threshold) Node 1 TxnCoordSender Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ Tx1 is expired! Heartbeat が一定時間途絶えた場合、Tx (Node) が死んでいると判 断できる。この Tx の生死を判断する閾値が “Transaction Liveness Threshold”。多分デフォルト 5秒。 https://github.com/cockroachdb/cockroach/blob/v20.2.5/pkg/kv/kvserver/txnwait/queue.go#L46 ~ Heartbeat key1 (t0): x0 key1 (t1): x1 (intent:Tx1)

Slide 63

Slide 63 text

Node 1 TxnCoordSender Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ Tx1 is expired! key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> x1 (intent:Tx1) 2. Check 1. Read \ イッタカ... / Heartbeat   補足 (Transaction Liveness Threshold) Tx1 を管理する Node が死んだ場合でも、他の Tx2 が write intent 読み込み Transaction Record を確認した際に、正しく「死んだ」と判 断できる。 Node 2

Slide 64

Slide 64 text

Node 1 TxnCoordSender Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: ABORTED key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> x0 ABORT Read \ サラバダ... / Heartbeat   補足 (Transaction Liveness Threshold) Tx1 が「死んだ」と判断された場合、それを見つけた Tx2 を管理する Node 2 が Tx1 の Transaction Record の値を ABORTED に更新 し、Tx2 は 1つ前の値 x0 を Read する (t0 < t1 < t2 の場合)。 Node 2

Slide 65

Slide 65 text

Read の動作 補足 (Transaction Record が作成される条件) \ サラニダッセンスルヨ /

Slide 66

Slide 66 text

補足 (Transaction Record が作成される条件) Node 1 TxnCoordSender Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: XXXXXX key1 (t0): x0 key1 (t1): x1 (intent:Tx1) 1. COMMIT が実行された時。(※詳細は Parallel Commits で) 2. TxnCoordSender が Heartbeat を実行した時。 3. Tx が強制的に ABORT された時。 Create \ ジョウケン /

Slide 67

Slide 67 text

補足 (Transaction Record が作成される条件1) Node 1 Tx1 (t1) BEGIN; Write (key1, x1); COMMIT; Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING 1. COMMIT が実行された時 (STAGING)。 ※何故 COMMIT のタイミングなのかについては後述する   Parallel Commits 参照。 When it COMMITs \ コミット / key1 (t0): x0 key1 (t1): x1 (intent:Tx1)

Slide 68

Slide 68 text

補足 (Transaction Record が作成される条件2) Node 1 TxnCoordSender Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: PENDING 2. TxnCoordSender が Heartbeat を実行した時。 ※Heartbeat は 1秒間隔なので、Tx 内の最初の Write から   1秒経つと Transaction Record が作成される。 When it Heartbeats \ イキテルヨ / key1 (t0): x0 key1 (t1): x1 (intent:Tx1)

Slide 69

Slide 69 text

Node 1 Tx1 (t1) BEGIN; Write (key1, x1); … Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: PENDING key1 (t0): x0 key1 (t1): x1 (intent:Tx1) 3. Tx1 が key1 への Write は実行したが Transaction Record は まだ作成していない状態で障害が発生すると、write intent は 存在するが対応する Transaction Record が無い、という状態 になる。   補足 (Transaction Record が作成される条件3) ~ Write Not yet...

Slide 70

Slide 70 text

Node 1 Range : Set of KV date (512BM) key1 (t1): x1 (intent:Tx1) Node 2 Tx2 (t2) Read (key1); -> x1 (intent:Tx1) 2. Check 1. Read \ ナイ / 3. 他の Tx2 が write intent 読み込んだ際に、対応する Transaction Record が存在しないことを検知する。   ※ただ し、この時点で Node 1 が死んでいるか否かは判断 できない (単純に Node 1 が処理途中の可能性が有る)。 補足 (Transaction Record が作成される条件3) key1 (t0): x0

Slide 71

Slide 71 text

Node 1 Range : Set of KV date (512BM) Node 2 Check Timestamp \ カクニン / 3. Transaction Record が無い場合は、読み込んだ write intent の Timestamp が Transaction Liveness Threshold 以内か否 かを確認する。 補足 (Transaction Record が作成される条件3) key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> x1 (intent:Tx1) key1 (t0): x0

Slide 72

Slide 72 text

Node 1 Range : Set of KV date (512BM) Node 2 Treat as PENDING \ マツワ / 3. write intent の Timestamp t1 が Transaction Liveness Threshold 以内の場合 PENDING として扱い、待つ。 多分 (Current time - t1) < 5 の場合。 補足 (Transaction Record が作成される条件3) key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> x1 (intent:Tx1) key1 (t0): x0

Slide 73

Slide 73 text

Node 1 Range : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: ABORTED key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Node 2 Tx2 (t2) Read (key1); -> x0 ABORT Read \ シンダナ / 補足 (Transaction Record が作成される条件3) 3. write intent の Timestamp t1 が Transaction Liveness Threshold の範囲外 (古い) の場合、Tx1 を ABORT させるた めに Transaction Record を作成する。 多分 (Current time - t1) > 5 の場合。

Slide 74

Slide 74 text

Read の動作 つづき \ モドッテキタヨ /

Slide 75

Slide 75 text

Read した値が “write intent” だった場合 (MISSING) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); Tx1’s “Transaction Record” ------------------------------------ MISSING Tx Record が無い場合は “write intent” の Timestamp が “Transaction Liveness Threshold” の範囲内か否かをチェックす る。 key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> ??? 無い...? 再掲

Slide 76

Slide 76 text

Read した値が “write intent” だった場合 (MISSING) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); “write intent” の Timestamp が “Transaction Liveness Threshold” 以内 の場合、PENDING として扱い、待つ。 key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> wait... Tx1’s “Transaction Record” ------------------------------------ MISSING

Slide 77

Slide 77 text

Read した値が “write intent” だった場合 (MISSING) Range : Set of KV date (512BM) Tx1 (t1) BEGIN; Write (key1, x1); ※Tx1 に「何らかの  問題が発生した」 判 断される。 key1 (t0): x0 key1 (t1): x1 (intent:Tx1) Tx2 (t2) Read (key1); -> x0 “write intent” の Timestamp が “Transaction Liveness Threshold” の範 囲外 (古い) の場合、ABORT として処理し x0 を Read する。 Tx1’s “Transaction Record” ------------------------------------ State: ABORTED

Slide 78

Slide 78 text

Parallel Commits \ パラレル /

Slide 79

Slide 79 text

Not Parallel Commits \ ムカシ / 初期の頃 (~ v2.0) の実装

Slide 80

Slide 80 text

v2.0 まで BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline Tx 内の Statement は順番に 実行される。

Slide 81

Slide 81 text

v2.0 まで BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline Write1 実行       Tx Record 作成 (PENDING) 最初の Statement と一緒に Tx Record も作成される。

Slide 82

Slide 82 text

v2.0 まで BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline 各 Statement は並列実行でき ないので、順番に実行される。 Write2 実行

Slide 83

Slide 83 text

v2.0 まで BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline 各 Statement は並列実行でき ないので、順番に実行される。 Write3 実行

Slide 84

Slide 84 text

v2.0 まで BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline 最後に、Tx Record の値を PENDING -> COMMITTED に変える処理が実行される。 COMMIT 実行      Tx Record 更新 (COMMIT)

Slide 85

Slide 85 text

v2.0 まで BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline Tx 内の Statement は順番に 実行されるので、処理時間は O(n) になる。  ※n = Num of Statements COMMIT (Tx Record の更新 処理) も入れると O(n+1) にな る。

Slide 86

Slide 86 text

Not Parallel Commits \ チョットマエ / ちょっと前 (v2.1 ~ v19.1) までの実装

Slide 87

Slide 87 text

BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline v2.1 で Pipelining という機能 が実装され、Tx 内の各 Statement は並列で実行され るようになった。 v2.1 ~ v19.1 まで (Pipelining)

Slide 88

Slide 88 text

v2.1 ~ v19.1 まで (Pipelining) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline Write1 実行       Tx Record 作成 (PENDING) Write2 実行      Write3 実 行 各 Statement を並列で実行。 ただし、全ての Statement の 書き込み完了が返ってくるまで Tx Record の値を COMMIT に更新できない。

Slide 89

Slide 89 text

v2.1 ~ v19.1 まで (Pipelining) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline 全ての Statement の書き込み 完了が返ってきたら、Tx を COMMIT する (Tx Record の 値を COMMITTED に更新す る)。 COMMIT 実行      Tx Record 更新 (COMMIT)

Slide 90

Slide 90 text

v2.1 ~ v19.1 まで (Pipelining) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline Pipelining により各 Statement を並列で実行でき るようになったので、理論上の 最短処理時間は O(2) になっ た。 ※この O(2) を O(1) にする  のが Parallel Commits。

Slide 91

Slide 91 text

BEGIN; Write (key1, x1); Read (key1); Write (key3, z1); COMMIT; Timeline なお、Statement 間に依存関 係が有る場合は、並列には実 行されず、ちゃんと順番に実行 される仕組みになっている。 v2.1 ~ v19.1 まで (Pipelining : Read-Your-Writes)

Slide 92

Slide 92 text

BEGIN; Write (key1, x1); Read (key1); Write (key3, z1); COMMIT; Timeline Write1 と Write3 は別々の key に対する Write であり、依 存関係はないので並列実行。 v2.1 ~ v19.1 まで (Pipelining : Read-Your-Writes)

Slide 93

Slide 93 text

BEGIN; Write (key1, x1); Read (key1); Write (key3, z1); COMMIT; Timeline Write1 と Write3 は別々の key に対する Write であり、依 存関係はないので並列実行。 Read は Write1 が更新した key1 の値を読む必要が有る (依存関係が有る) ので、 Write1 完了後に実行される。 v2.1 ~ v19.1 まで (Pipelining : Read-Your-Writes)

Slide 94

Slide 94 text

BEGIN; Write (key1, x1); Read (key1); Write (key3, z1); COMMIT; Timeline Tx 内の Statement 間に依存 関係が有る場合は、必ずしも O(2) になるわけではない。 ※あくまで理論上の最短が  O(2) になる感じ。  この “理論上の最短” を    O(2) から O(1) にするのが   Parallel Commits。 v2.1 ~ v19.1 まで (Pipelining : Read-Your-Writes)

Slide 95

Slide 95 text

Parallel Commits \ サイシン / 最新 (v19.2 ~) の実装

Slide 96

Slide 96 text

Parallel Commits (v19.2 ~) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline Parallel Commits は、 COMMIT の処理 (Tx Record の作成) も他の Statement と 並列で実行することで、処理時 間の理論上の最短を O(1) に するもの。 Tx 内で Write する key が全て 確定している必要があり、 Transaction Record は COMMIT のタイミングで作成 される。

Slide 97

Slide 97 text

Parallel Commits (v19.2 ~) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline 書き込み完了前 に COMMIT して 大丈夫か...?

Slide 98

Slide 98 text

Parallel Commits \ kwsk / COMMIT (Write) の動作

Slide 99

Slide 99 text

Parallel Commits (Write) Node 1 Range1 : Set of KV date (512BM) key1 (t0): x0 Range2 : Set of KV date (512BM) key2 (t0): y0 \ スタート / Client key1, key2 を更新する。 BEGIN; Write (key1, x1); Write (key2, y2); COMMIT;

Slide 100

Slide 100 text

Node 1 Range1 : Set of KV date (512BM) Range2 : Set of KV date (512BM) \ リクエスト / Client BEGIN; Write (key1, x1); Write (key2, y2); COMMIT; Write のタイミングではまだ Tx Record は作成しない。 Parallel Commits (Write) key1 (t0): x0 key2 (t0): y0 key1 (t1): x1 (intent:Tx1) key2 (t1): y1 (intent:Tx1) Write Write

Slide 101

Slide 101 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) key1 (t1): x1 (intent:Tx1) key2 (t1): y1 (intent:Tx1) \ ヘイレツ / Parallel Write Client BEGIN; Write (key1, x1); Write (key2, y2); COMMIT; COMMIT のタイミングで Tx Record を作成する。この時、State には STAGING を設定 し、一緒に「更新対象の key の一覧 (key1, key2)」の情報を Tx Record 内に含める。 Parallel Commits (Write) key1 (t0): x0 key2 (t0): y0

Slide 102

Slide 102 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) \ カンリョウ / Write OK Client BEGIN; Write (key1, x1); Write (key2, y2); COMMIT; Write OK Write OK 各 Write 及び Tx Record の作成が完了したことを確認する。 Parallel Commits (Write) key1 (t1): x1 (intent:Tx1) key2 (t1): y1 (intent:Tx1) key1 (t0): x0 key2 (t0): y0

Slide 103

Slide 103 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) \ オワッタヨ / Client BEGIN; Write (key1, x1); Write (key2, y2); COMMIT; COMMIT Complete 各 Write 及び Tx Record の作成が完了したことを確認した時点で、Client に COMMIT 完了を返す。 Parallel Commits (Write) key1 (t1): x1 (intent:Tx1) key2 (t1): y1 (intent:Tx1) key1 (t0): x0 key2 (t0): y0

Slide 104

Slide 104 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED Keys: key1, key2 Range2 : Set of KV date (512BM) \ ヒドウキ / Client Client に COMMIT 完了を返した後に「非同期」かつ並列で Tx Record の更新 (COMMITTED に更新) と write intent の削除を実施する。他の Tx が Read する可能 性が有るため、非同期ではあるが「できるだけ速く」更新する。 State is COMMITTED Resolve intent Resolve intent Parallel Commits (Write) key1 (t1): x1 (intent:Tx1) key2 (t1): y1 (intent:Tx1) key1 (t0): x0 key2 (t0): y0

Slide 105

Slide 105 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED Keys: key1, key2 Range2 : Set of KV date (512BM) \ オワリ / Client write intent の処理完了後に、Tx Record は削除され更新した値の状態が確定 (COMMIT 済みに確定) する。 Parallel Commits (Write) key1 (t1): x1 key2 (t1): y1 key1 (t0): x0 key2 (t0): y0

Slide 106

Slide 106 text

Parallel Commits \ モット kwsk / Read の動作

Slide 107

Slide 107 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 key1 (t1): x1 (intent:Tx1) Range2 : Set of KV date (512BM) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Node 2 \ リードスルヨ / \ ヘイレツ / Node 1 が Tx1 で key1, key2 を更新し、Node 1 の処理途中 (Tx Record の State が STAGING のタイミング) で Node 2 が Tx2 で key1 を Read する。 Parallel Write Parallel Commits (Read) Tx2 (t2)    ※t0 < t1 < t2 Read (key1);

Slide 108

Slide 108 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ リード / \ ショリチュウ... / Node 2 が Tx2 で key1 を Read すると、write intent (COMMIT or ABORT が不定) に なっている。また、Node 1 は処理中であるため Tx1 の Tx Record に定期的に Heartbeat が送信されている。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Read key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Parallel Commits (Read) Heartbeat Write OK Write OK Write OK

Slide 109

Slide 109 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ カクニン / \ ショリチュウ... / Node 2 (Tx2) が key1 の状態を確認するために Tx Record を参照すると、State が STAGING であることがわかる。また、Node 1 からの Heartbeat も継続しているため Node 1 (Tx1) は生きている (処理中) であることも確認できる。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Check key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Parallel Commits (Read) Heartbeat Write OK Write OK Write OK

Slide 110

Slide 110 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ マツワ / \ イキテルヨ / Tx1 を管理する Node1 からの Heartbeat が続いているため、Node 1 (Tx1) は生きて いる (処理中) と判断し、Node 2 (Tx2) は Tx1 が完了するまで待つ。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); -> wait... Heartbeat key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t0): y0 Parallel Commits (Read) key2 (t1): y1 (intent:Tx1) Write OK Write OK Write OK

Slide 111

Slide 111 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ タイキ / \ ショリチュウ... / Tx1 は処理中... (Heartbeat は継続) Tx2 は待機... (Tx1 の完了待ち) Tx2 (t2)    ※t0 < t1 < t2 Read (key1); -> wait... key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Parallel Commits (Read) Heartbeat Write OK Write OK Write OK

Slide 112

Slide 112 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED Range2 : Set of KV date (512BM) Node 2 \ オワッタッポイ / \ オワッタヨ / Tx1 の処理が完了すると、Tx2 (Node 2) は Tx1 にて更新された値 (x1) を Read する。 後述する Status Recovery Procedure は非常に重い処理であるため、Tx1 を管理する Node 1 が生きている場合は、Tx1 が COMMIT されるまで待つ。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); -> x1 Read State is COMMITTED key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Parallel Commits (Read)

Slide 113

Slide 113 text

Parallel Commits \ サラニ kwsk / 障害発生時の Read (Status Recovery Procedure)

Slide 114

Slide 114 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 key1 (t1): x1 (intent:Tx1) Range2 : Set of KV date (512BM) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Node 2 \ リードスルヨ / \ ヘイレツ / Case 1 : Node 1 が Tx1 で key1, key2 を更新し、Node 1 の処理途中 (Tx Record の State が STAGING のタイミング) で Node 2 が Tx2 で key1 を Read する。また、全て の write intent 書き込み完了後に Node 1 で障害が発生する。 Parallel Write   Status Recovery Procedure1 Tx2 (t2)    ※t0 < t1 < t2 Read (key1);

Slide 115

Slide 115 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 key1 (t1): x1 (intent:Tx1) Range2 : Set of KV date (512BM) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Node 2 \ リードスルヨ / 全ての write intent 書き込み完了後に Node 1 で障害が発生する。また、Node 1 の障 害に起因して Tx1 の Tx Record への Heartbeat が途切れる。   Status Recovery Procedure1 ~ Heartbeat Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Write OK Write OK Write OK

Slide 116

Slide 116 text

Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ リード / Node 2 が Tx2 で key1 を Read すると、write intent (COMMIT or ABORT が不定) に なっている。また、Node 1 に障害が発生し Heartbeat が途切れたため、Tx1 は expired となる。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Read key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure1 Heartbeat

Slide 117

Slide 117 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ カクニン / Node 2 (Tx2) が key1 の状態を確認するために Tx Record を参照すると、State が STAGING であることがわかる。また、Node 1 からの Heartbeat が途切れているため Node 1 (Tx1) が死んだと判断する。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Check (Tx1 is expired) key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure1 Node 1

Slide 118

Slide 118 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ サラニカクニン / Tx Record に含まれている更新対象の key の情報を基に、Tx1 の更新対象である key2 の write intent が作成されているかを確認する。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Check key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure1 Node 1

Slide 119

Slide 119 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ コミットダナ / Tx Record (STAGING) 内に含まれている key の write intent が全て書き込まれている 場合、implicitly committed (暗黙的な COMMIT である) として扱い、Tx2 (Node 2) は write intent の値を Read する。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); -> x1 Read key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure1 Node 1

Slide 120

Slide 120 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: COMMITTED Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ コミットダヨ / 他の Tx が Status Recovery Procedure を実行しなくても済むように、Node 2 が Tx1 の Tx Record の State を COMMITTED に更新する。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure1 Node 1 State is COMMITTED

Slide 121

Slide 121 text

  Status Recovery Procedure2 Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ リードスルヨ / \ ヘイレツ / Case 2 : Node 1 が Tx1 で key1, key2 を更新し、Node 1 の処理途中 (Tx Record の State が STAGING のタイミング) で Node 2 が Tx2 で key1 を Read する。また、key2 の write intent 作成前に Node 1 で障害が発生する。 Parallel Write key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Tx2 (t2)    ※t0 < t1 < t2 Read (key1);

Slide 122

Slide 122 text

  Status Recovery Procedure2 Node 1 Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ リードスルヨ / 一部の write intent 書き込み完了前に Node 1 で障害が発生する。また、Node 1 の 障害に起因して Tx1 の Tx Record への Heartbeat が途切れる。 key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); ~ Heartbeat Write OK Write OK

Slide 123

Slide 123 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ リード / Node 2 が Tx2 で key1 を Read すると、write intent (COMMIT or ABORT が不定) に なっている。また、Node 1 に障害が発生し Heartbeat が途切れたため、Tx1 は expired となる。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Read key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure2 Node 1 Heartbeat

Slide 124

Slide 124 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ カクニン / Node 2 (Tx2) が key1 の状態を確認するために Tx Record を参照すると、State が STAGING であることがわかる。また、Node 1 からの Heartbeat が途切れているため Node 1 (Tx1) が死んだと判断する。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Check (Tx1 is expired) key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t0): y0 Node 1   Status Recovery Procedure2 key2 (t1): y1 (intent:Tx1)

Slide 125

Slide 125 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ ナイ / Tx Record に含まれている更新対象の key の情報を基に、Tx1 の更新対象である key2 の write intent が作成されているかを確認する。しかし、key2 の write intent は存 在していないことが確認される。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Check key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t0): y0 Node 1   Status Recovery Procedure2 key2 (t1): y1 (intent:Tx1)

Slide 126

Slide 126 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: STAGING (expired) Keys: key1, key2 Range2 : Set of KV date (512BM) Node 2 \ アボートダナ / Tx1 は ABORT したものとして扱い、Tx2 (Node 2) は x0 を Read する。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); -> x0 Read Node 1 key1 (t0): x0 key2 (t0): y0   Status Recovery Procedure2 key1 (t1): x1 (intent:Tx1) key2 (t1): y1 (intent:Tx1)

Slide 127

Slide 127 text

Range1 : Set of KV date (512BM) Tx1’s “Transaction Record” ------------------------------------ State: ABORTED Range2 : Set of KV date (512BM) Node 2 \ シンダッポイ / 他の Tx が Status Recovery Procedure を実行しなくても済むように、Node 2 が Tx1 の Tx Record の State を ABORTED に更新する。 Tx2 (t2)    ※t0 < t1 < t2 Read (key1); Node 1 State is ABORTED key1 (t1): x1 (intent:Tx1) key1 (t0): x0 key2 (t1): y1 (intent:Tx1) key2 (t0): y0   Status Recovery Procedure2

Slide 128

Slide 128 text

Parallel Commits (v19.2 ~) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Timeline COMMIT 時に作成する Tx Record (STAGING) の中に更 新対象の key の一覧を含める ことで、処理時間を (最短で) O(1) にしつつ、他の Tx の Read も正しく処理できるように している。

Slide 129

Slide 129 text

Parallel Commits (v19.2 ~) BEGIN; Write (key1, x1); Write (key2, y1); Write (key3, z1); COMMIT; Update Tx Record & Remove write intent Timeline 非同期 (async) Client に COMMIT 完了を返し た後に、非同期で Tx Record の値を (できるだけ速く) COMMITTED に更新し、write intent を削除する。 Status Recovery Procedure は「重い処理」であり、通常 (Gateway Node が生きてる場 合) は COMMIT 完了を待つ が、障害発生時は他の Node で適切に対処できる。

Slide 130

Slide 130 text

話せなかったこと \ ホカニモイロイロアルヨ /

Slide 131

Slide 131 text

話せなかったこと ● Tx の競合を解決したり一貫性を確保したりするために、他にもいろ んな機能があります。 ○ Max clock offset enforcement ○ Timestamp cache ○ Concurrency manager ○ Lock table ○ TxnWaitQueue ○ Read refreshing ● 興味がある人はドキュメントを是非読んでみてください。 ○ https://www.cockroachlabs.com/docs/stable/architecture/transaction-layer.html

Slide 132

Slide 132 text

まとめ \ マトメ /

Slide 133

Slide 133 text

● Transaction Record を使って分散 Tx を実現している。 ● Parallel Commits で性能向上を図っている。 ● 今回紹介した機能以外の機能も使って Tx の競合を解決した り一貫性を確保したりしている。 まとめ

Slide 134

Slide 134 text

参考情報 ● https://www.cockroachlabs.com/docs/stable/architecture/transaction-layer.html ● https://www.cockroachlabs.com/docs/v20.2/architecture/life-of-a-distributed-transaction. html ● https://www.cockroachlabs.com/blog/parallel-commits/ ● https://www.cockroachlabs.com/blog/transaction-pipelining/ ● https://github.com/cockroachdb/cockroach/blob/master/docs/tech-notes/encoding.md

Slide 135

Slide 135 text

おまけ \ オマケ /

Slide 136

Slide 136 text

おまけ (実際の KV データを覗いてみる) root@cockroach-1:26257/defaultdb> select * from test; id | c1 | c2 | c3 -----+----------+-----------+---------- 1 | foo | bar | baz 2 | hoge | fuga | piyo 3 | (・ω・´) | (´・ω・`) | m9(^Д^) (3 rows) root@cockroach-1:26257/defaultdb> update test set c1 = 'foobar' where id = 1; UPDATE 1 Time: 15ms total (execution 15ms / network 0ms) root@cockroach-1:26257/defaultdb> root@cockroach-1:26257/defaultdb> select * from test; id | c1 | c2 | c3 -----+----------+-----------+---------- 1 | foobar | bar | baz 2 | hoge | fuga | piyo 3 | (・ω・´) | (´・ω・`) | m9(^Д^) (3 rows) Step 1. テスト用の TABLE Step 2. id = 1 の record を更新 (foo -> foobar)

Slide 137

Slide 137 text

おまけ (実際の KV データを覗いてみる) root@cockroach-1:26257/defaultdb> begin; BEGIN Time: 0ms total (execution 0ms / network 0ms) root@cockroach-1:26257/defaultdb OPEN> root@cockroach-1:26257/defaultdb OPEN> update test set c1 = 'foobaz' where id = 1; UPDATE 1 Time: 2ms total (execution 2ms / network 0ms) root@cockroach-1:26257/defaultdb OPEN> root@cockroach-1:26257/defaultdb OPEN> select * from test; id | c1 | c2 | c3 -----+----------+-----------+---------- 1 | foobaz | bar | baz 2 | hoge | fuga | piyo 3 | (・ω・´) | (´・ω・`) | m9(^Д^) (3 rows) Time: 1ms total (execution 1ms / network 0ms) root@cockroach-1:26257/defaultdb OPEN> Step 3. Tx 内で id = 1 を更新 (foobar -> foobaz) Tx は COMMIT せず OPEN のまま

Slide 138

Slide 138 text

おまけ (実際の KV データを覗いてみる) Byte 形式 Transaction Record key: 0x016B12BE8989000174786E2D79AE144DD9264CF2AC519A81DE7CFFBE00 value: 0x12040800100018002000280032480F1CFC56030A350A1079AE144DD9264CF2AC519A81DE7CFFBE1A03BE89892A0C08B0B4B2C7E5 A0FEB416100230E8AA594A0A08819EE0A1EA9FFEB4162A0A08A0AFB9B7BBA7FEB416 Write Intent key: 0xBE89898800 value: 0x0A370A1079AE144DD9264CF2AC519A81DE7CFFBE1A03BE89892A0C08B0B4B2C7E5A0FEB416100230E8AA5938014A0A08819EE0A1 EA9FFEB416120C08B0B4B2C7E5A0FEB41610021800200C2817 A) “Step 3.” の Tx (OPEN 中の Tx) の Transaction Record B) “Step 3.” の Tx (OPEN 中の Tx) 内で UPDATE した id = 1 の record の Write Intent

Slide 139

Slide 139 text

おまけ (実際の KV データを覗いてみる) Byte 形式 Rows [id = 1 (c1 = foobaz)] key : 0xBE898988001669F90658EC9A30000000020D value : 0x76AE0A090A2606666F6F62617A1603626172160362617A [id = 1 (c1 = foobar)] key : 0xBE898988001669F8F845F4657A09 value : 0xCC6DEB4C0A2606666F6F6261721603626172160362617A [id = 1 (c1 = foo)] key : 0xBE898988001669F8AF87FB1ABD09 value : 0x4CF924910A2603666F6F1603626172160362617A [id = 2] key : 0xBE898A88001669F8B3E074FA7609 value : 0x65EEC34A0A2604686F676516046675676116047069796F [id = 3] key : 0xBE898B88001669F8E34AC654C609 value : 0xC11CE7CF0A260C28E383BBCF89E383BBC2B429160D28C2B4E383BBCF89E383BB602916086D39285ED0945E29 C) “Step 3.” の時点での TABLE ”test” の各 record

Slide 140

Slide 140 text

おまけ (実際の KV データを覗いてみる) Decode Transaction Record key: /Local/Range/Table/54/1/1/Transaction/"79ae144d-d926-4cf2-ac51-9a81de7cffbe" value: meta={id=79ae144d key=/Table/54/1/1 pri=0.06815679 epo=0 ts=1615095747.046054448,2 min=1615095713.949552385,0 seq=0} lock=true stat=PENDING rts=0,0 wto=false max=0,0 Write Intent key: /Table/54/1/1/0 value: 1615095747.046054448,2 {Txn:id=79ae144d key=/Table/54/1/1 pri=0.06815679 epo=0 ts=1615095747.046054448,2 min=1615095713.949552385,0 seq=1 Timestamp:1615095747.046054448,2 Deleted:false KeyBytes:12 ValBytes:23 RawBytes:[] IntentHistory:[] MergeTimestamp:} A) “Step 3.” の Tx (OPEN 中の Tx) の Transaction Record B) “Step 3.” の Tx (OPEN 中の Tx) 内で UPDATE した id = 1 の record の Write Intent

Slide 141

Slide 141 text

おまけ (実際の KV データを覗いてみる) Decode Rows [id = 1 (c1 = foobaz)] key : /Table/54/1/1/0/1615095747.046054448,2 value : "v\xae\n\t\n&\x06foobaz\x16\x03bar\x16\x03baz" [id = 1 (c1 = foobar)] key : /Table/54/1/1/0/1615095686.598255994,0 value : "\xccm\xebL\n&\x06foobar\x16\x03bar\x16\x03baz" [id = 1 (c1 = foo)] key : /Table/54/1/1/0/1615095374.173379261,0 value : "L\xf9$\x91\n&\x03foo\x16\x03bar\x16\x03baz" [id = 2] key : /Table/54/1/2/0/1615095392.837630582,0 value : "e\xee\xc3J\n&\x04hoge\x16\x04fuga\x16\x04piyo" [id = 3] key : /Table/54/1/3/0/1615095596.484809926,0 value : "\xc1\x1c\xe7\xcf\n&\f( ・ω・´)\x16\r(´・ω・`)\x16\bm9(^Д^)" C) “Step 3.” の時点での TABLE ”test” の各 record

Slide 142

Slide 142 text

Thank you!