Upgrade to Pro — share decks privately, control downloads, hide ads and more …

txkv_v06_pub.pdf

tom--bo
October 18, 2022

 txkv_v06_pub.pdf

tom--bo

October 18, 2022
Tweet

More Decks by tom--bo

Other Decks in Technology

Transcript

  1. TxKV Design

  2. 設計⽅針 • Jim Gray著のTransaction Processingをベースに トランザクショナルなKVSを実装 • シングルバージョン(not MVCC) •

    SS2PLによるロックで排他制御 • データ本体のデータ構造 • 最初はハッシュマップで実装 • 追記型ではなくインプレースに更新 • あとからB⽊に置き換える • gRPCでサーバ起動
  3. 現状 (2022/10/18) • ストレージはインメモリ • OSシャットダウン後は、KVSのデータは消失 • データサイズは固定⻑: key, value

    共にint64の128バイト • 障害回復なし • デッドロック検出なし
  4. ⽬標 • 有名なConcurrency Control(CC)プロトコルの理解と実装 • “An Empirical Evaluation of In-Memory

    Multi-Version Concurrency Control (VLDB2017)”
  5. Internal API • db_init() • start_tx() • put() • get()

    • del() • commit_tx() • rollback_tx() External API • grpcのサービス定義 service MyKV { rpc Connect (google.protobuf.Empty) returns (ConnectionReply) {} rpc Begin (BaseRequest) returns (ErrorReply) {} rpc Commit(BaseRequest) returns (ErrorReply) {} rpc Rollback(BaseRequest) returns (ErrorReply) {} rpc Get(KeyRequest) returns (GetReply) {} rpc Put(WriteRequest) returns (ErrorReply) {} rpc Del(KeyRequest) returns (ErrorReply) {} } cf) https://github.com/tom--bo/tx_kv/blob/main/src/grpc/protos/kv.proto
  6. コンポーネントイメージ

  7. コンポーネントイメージ (grpc_server.cpp/.h) gRPCのサーバモックに任せる。 Request, Responseのキュー管理 しない。 (kv_server.cpp/.h) サーバ機能実装 (未実装) undo,redoに当たるものはメモリ上で

    TxCBに持たせてはいる 実装なし (MapStore.cpp/.h) (LockManager.cpp/.h) データ管理とロック管理 (TxManager.cpp/.h) データ管理とロック管理
  8. None
  9. KvClient (grpc_client) TPMonitor (grpc_server) KvServer TxManager MapStore LockManager (未実装) undo,redoに当たるものはメモリ上で

    TxCBに持たせてはいる (未実装) この部分はKvServerに吸収した
  10. TxManager TxID global_txid -- TxID(atomic) MapStore *store -- RMへのポインタ -

    start_tx() -- txid払い出し - commit_tx() - rollback_tx() TxCB TxID txid LockRequest *lock_head -- Txで取ったロックのリスト LockRequest *anchor -- ロックのリストの最後尾 LockRequest *wait -- このTxが待っているロック UndoList *undo_head -- このTxのUndoリスト先頭 略語 CB: Context Block RM: Resource Manager LM: Lock Manager KVServer TxManager *txManager -- TxManagerへのポインタ MapStore *store -- RMへのポインタ ulong global_cid -- グローバルコネクションid - db_init() - connect() - start_tx() -- txid払い出し - commit_tx() - rollback_tx() - get() - put() - del() MapStore (RM) MapStore store -- ハッシュマップのストア LockManager *lm -- ロックマネージャのポインタ - commit_tx() - get() - put() - del() - rollback_tx() LockHash Mutex lock_head_mutex -- lockheadを作成・削除するときに -- 取るグローバルのMutex HashMap lock_hash -- keyとlock_headのハッシュマップ - FindLockHead() -- あるkeyのlock headを返す - CreateLockHead() -- あるkeyのlock headを作成 LockManager (LM) HashMap *lock_hash -- keyとlock_headのハッシュマップ - Lock() - UnLock() - UnlockAll() -- あるTxの持つ全てのlockの解除 - LockCompat -- 2つのlock_modeに互換性があるか判断 - GrantGroup -- GrantGroupのlock_modeの更新 KVClient TxCB *txcb KvServer *srv -- KVserverへのポインタ - Connect() - Begin() -- txid取得 - Get() - Put() - Del() - Commit () - Rollback () - Close() TPMonitor ConnectionMap *ConnMap -- connとtxcbのHashMap - Connect() - Begin() - Get() - Put() - Del() - Commit() - Rollback() - Close() LockHead ... LockRequest ...
  11. TxCB TxCB (Transaction Context Block) • start_tx()したときにTxManagerで⽣成 • TPMonitorが<connection_id, TxCB>の組み合わせのハッシュマップで

    管理 • 開始されたトランザクションの情報を保持 • このトランザクションで取得したロックのリスト • このトランザクションで更新したデータのUndoリスト TxCB TxID txid LockRequest *lock_head -- Txで取ったロックのリスト LockRequest *anchor -- ロックのリストの最後尾 LockRequest *wait -- このTxが待っているロック UndoList *undo_head -- このTxのUndoリスト先頭 lock_head LockRequest LockRequest LockRequest anchor undo_haed UndoRecord TxID txid OperationType op_type bool is_null ulong val_before = 10 ulong val_after UndoRecord *next UndoRecord UndoRecord UndoRecord *tran_next *tran_next
  12. ロックのデータ構造(1) LockManager HashMap *lock_hash -- keyとlock_headのハッシュマップ - Lock() - UnLock()

    - UnlockAll() -- あるTxの持つ全てのlockの解除 - LockCompat() -- 2つのlock_modeに互換性があるか判断 - GrantGroup() -- GrantGroupのlock_modeの更新 LockHash Mutex lock_head_mutex -- lockheadを作成・削除するときに -- 取るグローバルのMutex HashMap lock_hash -- keyとlock_headのハッシュマップ - FindLockHead() -- あるkeyのlock headを返す - CreateLockHead() -- あるkeyのlock headを作成 LockManager • リソースマネージャ(RM)がLockManagerを介してロックを取得する • Lockの取得はLockHeadへのLockRequestのエンキュー • ロックを取得するスレッドはTxCBへのポインタを渡して、状況に応じて TxCBを更新する LockHash • LockHashは<key, LockHead>のハッシュマップでキーへのLockRequestを 管理する • LockHashから⾒つけたLockHeaderにLockRequestを追加する 1 3 10 20 ... LockHead LockHead LockHead LockHead LockRequest LockRequest LockRequest LockRequest (LockHash) (LockHead) (LockRequest) record値
  13. ロックのデータ構造(2) LockHead Mutex mu LockRequest *queue LockMode granted_mode LockRequest LockHead

    *head LockRequest *next LockStatus status LockMode mode LockMode convert_mode TxCB *txcb LockRequest *tran_next LockHead • 1つのレコードに対するロック(LockRequest)をqueueで保持 • レコードに対して許可しているgranted_modeを管理 • LockHead⾃体の⽣成・削除はLockHashのMutexで保護 LockRequest • レコードに対するロックリクエスト • LockModeは現在S, Xのみ • Sロックを取っている状態でXロックを取る場合はconvert_modeを利⽤ • あるTxで保持しているロックのリストをtran_nextでキュー管理 • LockHeadのLockRequestキューの操作はLockHeadのMutexで保護 LockHead LockRequest LockRequest LockRequest LockRequest
  14. ロックのデータ構造(3) LockHead LockRequest LockHead LockRequest LockRequest LockHead LockRequest LockRequest LockRequest

    LockHead LockRequest LockRequest LockHead LockRequest LockHead LockRequest LockRequest Granted Modeの遷移 S lock S lock S lock S lock S lock S lock X lock X lock X lock X lock S lock (granted_mode) S X (Timestamp) (ts: 1) (ts: 2) (ts: 4) (ts: 3) (ts: 6) (ts: 5) S S S X
  15. ロックのデータ構造(4) LockHead LockRequest LockHead LockRequest LockRequest LockRequest Granted Modeの遷移 (granted_mode)

    S lock S lock S -> X S lock LockHead LockRequest LockRequest LockRequest S -> X S lock X lock LockHead LockRequest S -> X LockHead LockRequest LockRequest LockRequest S S lock S lock S lock LockHead LockRequest LockRequest X S -> X X lock Lock Conversion to X Lock (convert_modeに変換先のlock_modeを保持) LockRequest X lock LockRequest X lock (Timestamp) (ts: 1) X lock LockRequest LockRequest S lock (ts: 2) (ts: 4) (ts: 3) (ts: 6) (ts: 5) S S S S
  16. データ本体のデータ構造がHashMapなので、 S, Xのみを利⽤(実装⾃体はこの表のとおりに実装済み) S, Xのみなのでほとんど出番なし (今後拡張したら追記予定)

  17. ロックのデータ構造(5) 1 ... 10 ... 22 ... 86 ... LockHead

    LockHead LockRequest LockRequest LockRequest LockRequest LockHash TxCB (txid: 1) LockHead LockRequest LockRequest LockHead LockRequest LockRequest TxCB (txid:2) TxCB (txid: 3) *tran_next *tran_next *list_head *list_head *list_head TxCB, LockHash起点のLockRequestリスト
  18. 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager TxManager

    ① Connect() (cid = 3) cid = 3
  19. 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager TxManager

    cid = 3
  20. 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager TxManager

    ② Begin() (OK) cid = 3 start_tx() (*txcb) TxCB listhead anchor undo_head HashMap<cid, txcb> = { ... (3, *txcb), } new()
  21. 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager TxManager

    cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } listhead anchor undo_head
  22. 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager TxManager

    cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) Lock(key=1) listhead anchor undo_head
  23. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) Lock(key=1) 1 3 10 20 ... LH LR (LockHead) (LockRequest) lock_head_mutex CheckLock(key=1) Locked Unlocked listhead anchor undo_head
  24. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) Lock(key=1) 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex 1. Lock() 2. Create LockHead LH listhead anchor undo_head
  25. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) Lock(key=1) 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex UnLock() LH listhead anchor undo_head
  26. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) Lock(key=1) 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex 1. Lock() LH lock_queue_mutex LR 2. Enqueue Lock Request 3. Enqueue Lock Request listhead anchor undo_head
  27. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex Unlock() LH LR *LR Lock(key=1) listhead anchor undo_head
  28. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex LH LR *LR MapStore 1 10 3 ... ... ... key : val ① Put(1,10) ② Add.undo undo listhead anchor undo_head
  29. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ③ Put(1, 10) (OK) Put(1, 10) 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex LH LR *LR MapStore 1 10 3 ... ... ... key : val ① Put(1,10) ② Add.undo undo listhead anchor undo_head
  30. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex LH LR *LR MapStore 1 10 3 ... ... ... key : val undo listhead anchor undo_head
  31. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } ④ commit (OK) Commit 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex LH LR *LR MapStore 1 10 3 ... ... ... key : val ① Lock (③Unlock) undo ② Release ④ Release (Commitに⾄るケース) ⑤ Release Unlock(*txcb) Unlock(*txcb) listhead anchor undo_head
  32. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex LH LR *LR MapStore 1 10 3 ... ... ... key : val undo listhead anchor undo_head (Rollbackに⾄るケース)
  33. LockHash 処理イメージ (PUT) KvClient (grpc_client) TPMonitor (grpc_server) KvServer MapStore LockManager

    TxManager cid = 3 TxCB HashMap<cid, txcb> = { ... (3, *txcb), } 1 3 10 20 ... LH LR (LockHead) (LockRequest) Locked Unlocked lock_head_mutex LH LR *LR MapStore 1 (del) 3 ... ... ... key : val undo listhead anchor undo_head (Rollbackに⾄るケース) ④ Rollback (OK) Rollback ⑥ Release Unlock(*txcb) Unlock(*txcb) ① Undo ① Undo ② Lock (④Unlock) ③ Release ⑤ Release
  34. 今後の課題 • TBD

  35. Deadlock検知 • TBD