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

    View Slide

  2. 設計⽅針
    • Jim Gray著のTransaction Processingをベースに
    トランザクショナルなKVSを実装
    • シングルバージョン(not MVCC)
    • SS2PLによるロックで排他制御
    • データ本体のデータ構造
    • 最初はハッシュマップで実装
    • 追記型ではなくインプレースに更新
    • あとからB⽊に置き換える
    • gRPCでサーバ起動

    View Slide

  3. 現状 (2022/10/18)
    • ストレージはインメモリ
    • OSシャットダウン後は、KVSのデータは消失
    • データサイズは固定⻑: key, value 共にint64の128バイト
    • 障害回復なし
    • デッドロック検出なし

    View Slide

  4. ⽬標
    • 有名なConcurrency Control(CC)プロトコルの理解と実装
    • “An Empirical Evaluation of In-Memory Multi-Version
    Concurrency Control (VLDB2017)”

    View Slide

  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

    View Slide

  6. コンポーネントイメージ

    View Slide

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

    View Slide

  8. View Slide

  9. KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    TxManager
    MapStore
    LockManager
    (未実装)
    undo,redoに当たるものはメモリ上で
    TxCBに持たせてはいる
    (未実装)
    この部分はKvServerに吸収した

    View Slide

  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
    ...

    View Slide

  11. TxCB
    TxCB (Transaction Context Block)
    • start_tx()したときにTxManagerで⽣成
    • TPMonitorがの組み合わせのハッシュマップで
    管理
    • 開始されたトランザクションの情報を保持
    • このトランザクションで取得したロックのリスト
    • このトランザクションで更新したデータの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

    View Slide

  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はのハッシュマップでキーへのLockRequestを
    管理する
    • LockHashから⾒つけたLockHeaderにLockRequestを追加する
    1
    3
    10
    20
    ...
    LockHead
    LockHead
    LockHead
    LockHead
    LockRequest
    LockRequest LockRequest LockRequest
    (LockHash) (LockHead) (LockRequest)
    record値

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  16. データ本体のデータ構造がHashMapなので、
    S, Xのみを利⽤(実装⾃体はこの表のとおりに実装済み)
    S, Xのみなのでほとんど出番なし
    (今後拡張したら追記予定)

    View Slide

  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リスト

    View Slide

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

    View Slide

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

    View Slide

  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 = {
    ...
    (3, *txcb),
    } new()

    View Slide

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

    View Slide

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

    View Slide

  23. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  24. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  25. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  26. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  27. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  28. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  29. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  30. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  31. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  32. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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に⾄るケース)

    View Slide

  33. LockHash
    処理イメージ (PUT)
    KvClient
    (grpc_client)
    TPMonitor
    (grpc_server)
    KvServer
    MapStore
    LockManager
    TxManager
    cid = 3
    TxCB
    HashMap = {
    ...
    (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

    View Slide

  34. 今後の課題
    • TBD

    View Slide

  35. Deadlock検知
    • TBD

    View Slide