日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Rocksdb的事务(二):完整事务体系的 详细实现

發(fā)布時間:2023/11/27 生活经验 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Rocksdb的事务(二):完整事务体系的 详细实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 1. 基本事務(wù)操作
      • 1.1 TransactionDB -- Pessimistic
      • 1.2 OptimisticTransactionDB
      • 1.3 Read Uncommitted
      • 1.4 SavePoint 回滾部分事務(wù)操作
      • 1.5 SetSnapshot
      • 1.6 GetForUpdate
      • 1.7 RepeatableRead
    • 2. 實現(xiàn)
      • 2.1 WBWI(write batch with index) & WB(write batch)
      • 2.2 PessimisticTransaction 實現(xiàn)
      • 2.3 LockManager 以及 DeadLock detect 實現(xiàn)
        • 2.3.1 LockManager 加鎖實現(xiàn)
        • 2.3.2 DeadLock 檢測實現(xiàn)
      • 2.4 OptimisticTransaction
        • 2.4.1 kValidateSerial occ
        • 2.4.2 kValidateParallel occ
    • 3. 總結(jié)

很久之前簡單介紹了Rocksdb 事務(wù)的基本隔離性的應(yīng)用以及簡單實現(xiàn)的描述 Rocksdb 事務(wù): 隔離性的實現(xiàn)(一),其實里面有一些問題描述的非常模糊,對底層事務(wù)的實現(xiàn)細節(jié)講解得也不夠精確且也沒有形成遞進體系,所以今年年尾的最后一篇博客希望能夠?qū)?Rocksdb 的事務(wù)體系描述清楚,能夠有效幫助做數(shù)據(jù)庫的同學(xué)了解事務(wù)的基本實現(xiàn)(基本的隔離級別的實現(xiàn) rc、ru、si,分布式事務(wù)保證原子性的2PC 以及 事務(wù)周邊的rollback,死鎖檢測/死鎖避免 等都是如何做到的 ),更重要的是能夠看到大規(guī)模工業(yè)應(yīng)用之后的事務(wù)所暴露出來的問題 和 這一些問題對應(yīng)的優(yōu)質(zhì)解決方案,從而能夠讓我們將這一些思想靈活得借鑒到大規(guī)模的工業(yè)分布式環(huán)境之中。

接下來將詳細展開,以及在LSM-tree 模型下實現(xiàn)事務(wù)過程中存在的一些問題和對應(yīng)的優(yōu)化策略。

因為LSM-tree的 append模型,天然支持多版本,而且擁有WriteBatch 可以將多個版本的請求都緩存在內(nèi)存中,從而更有利得解決并發(fā)事務(wù)下的讀寫沖突和寫寫沖突問題。

本文涉及到的源代碼對應(yīng)的 rocksdb 版本是 6.25

1. 基本事務(wù)操作

Rocksdb 的事務(wù)實現(xiàn) 主要是通過TransactionDB 默認是(Pessimistic) 和 OptimisticTransactionDB 來提供事務(wù)操作。

1.1 TransactionDB – Pessimistic

使用 TransactionDB 進行事務(wù)操作,默認是 PessimisticTransactionDB,每次事務(wù)更新操作都會進行加鎖,會去檢測是否和其他事務(wù)有沖突。即 txn1 更新一個key1時會對當(dāng)前key加鎖,事務(wù)txn2 在 txn1 提交前嘗試更新這個key1 則會失敗。

TransactionDB* txn_db;
TransactionDBOptions txndb_opts;
TransactionOptions txn_opts;Options opts;
std::string value;opts.create_if_missing = true;
opts.compression = kNoCompression;Status s = TransactionDB::Open(opts, txndb_opts, "./txn_db", &txn_db);
PrintStatus("TransactionDB::Open", s);// 開啟事務(wù)
Transaction* txn = txn_db->BeginTransaction(WriteOptions(), txn_opts);
assert(txn != nullptr);PrintStatus("txn->Put", txn->Put("key1", "value1"));
/// 其他事務(wù)嘗試更新這個key1,則更新失敗,會有鎖超時問題
PrintStatus("txn_db->Put", txn_db->Put(WriteOptions(), "key1", "value2"));
// 最終的事務(wù)提交
PrintStatus("txn->Commit", txn->Commit());

1.2 OptimisticTransactionDB

在樂觀事務(wù)下,不同事務(wù)之間的沖突檢測不會在每次更新操作時候進行檢測,而是在事務(wù)提交的時候進行。

/*OptimisticTransactionDB test*/
OptimisticTransactionDB* optimize_txn_db;
OptimisticTransactionOptions opti_txn_opts;
OptimisticTransactionDBOptions opti_txn_db_opts;PrintStatus("OptimisticTransactionDB::Open",OptimisticTransactionDB::Open(opts, "./opti_txn_db", &optimize_txn_db));// 開啟樂觀事務(wù)
Transaction* opti_txn = optimize_txn_db->BeginTransaction(WriteOptions(), opti_txn_opts);
assert(opti_txn != nullptr);// 當(dāng)前事務(wù)更新 key1
PrintStatus("opti_txn->Put", opti_txn->Put("key1", "value1"));
// 外部事務(wù)在當(dāng)前事務(wù)期間更新了 同樣的 key1 ,這里會成功
PrintStatus("optimize_txn_db->Put", optimize_txn_db->Put(WriteOptions(), "key1", "value2"));
// commit 失敗
PrintStatus("opti_txn->Commit", opti_txn->Commit());

悲觀事務(wù) 和 樂觀事務(wù)主要就是沖突檢測的位置不同,所以悲觀事務(wù) 在事務(wù)沖突概率較高的場景下能夠保證提前發(fā)現(xiàn)沖突而更早的觸發(fā)沖突事務(wù)的回滾。在沖突概率不高的情況下,悲觀事務(wù)每一個更新(Put,Delete,Merge,GetForUpdate)都會做沖突檢測,會引入較多的競爭開銷,從而降低性能,所以沖突概率不高的場景可以嘗試樂觀事務(wù)DB。

1.3 Read Uncommitted

這個不是 rocksdb支持的隔離級別,rocksdb 默認只支持 RC 和 Repeatable Read

不同的事務(wù)之間只能讀到事務(wù)已經(jīng)提交的數(shù)據(jù),同一個事務(wù)內(nèi)部,能夠讀到未提交的數(shù)據(jù)。

// 事務(wù)寫入key1
PrintStatus("txn->Put", txn->Put("key1", "value1"));
// 讀到key1 的結(jié)果是 value1
PrintStatus("txn->Get", txn->Get(ReadOptions(), "key1", &value));
PrintStatus("txn->Delete", txn->Delete("key1"));
// Notfound
PrintStatus("txn->Get", txn->Get(ReadOptions(), "key1", &value));

因為未提交的事務(wù)都會在一個WriteBatch中,這樣當(dāng)前事務(wù)內(nèi)部按照操作順序能夠看到當(dāng)前操作之前的所有操作。

1.4 SavePoint 回滾部分事務(wù)操作

Transaction 提供了回滾當(dāng)前事務(wù)部分操作的能力,在事務(wù)中間的某一個位置設(shè)置一個 SavePoint,后面能會滾到這個位置。

// 當(dāng)前事務(wù)寫入
PrintStatus("txn->Put", txn->Put("key1", "value1"));
// 設(shè)置回滾點
txn->SetSavePoint();
// 刪除
PrintStatus("txn->Delete", txn->Delete("key1"));
// 嘗試讀,讀不到,已經(jīng)被刪除了
PrintStatus("txn->Get", txn->Get(ReadOptions(), "key1", &value));
// 回滾
txn->RollbackToSavePoint();
// 此時能夠讀到
PrintStatus("txn->Get", txn->Get(ReadOptions(), "key1", &value));

1.5 SetSnapshot

之前有描述,事務(wù)DB 會對每一個更新的key 進行加鎖,保證后續(xù)其他事務(wù)對 相同key的更新是失敗的。如果用戶想要在事務(wù)一開始的時候就標(biāo)識 后續(xù)所有寫入的key 都要進行獨占,那可以通過 開啟事務(wù)之后設(shè)置一個 SetSnapshot 來進行后續(xù)當(dāng)前事務(wù) 會獨占所有標(biāo)識的key,減少一部分的沖突檢測邏輯。

SetSnapshot 之前 我們下面的邏輯是正常的:

Transaction* txn = txn_db->BeginTransaction(WriteOptions(), txn_opts);
assert(txn != nullptr);
// 即使外部的事務(wù)操作成功,因為是在當(dāng)前事務(wù)更新之前更新的,并沒有沖突
PrintStatus("txn_db->Put", txn_db->Put(WriteOptions(), "key1", "value3"));
PrintStatus("txn->Put", txn->Put("key1", "value1"));PrintStatus("txn->Commit", txn->Commit());

通過 SetSnapshot 標(biāo)識 之后所有的更新都被當(dāng)前事務(wù)獨占,上面的外部事務(wù)更新就會失敗。

Transaction* txn = txn_db->BeginTransaction(WriteOptions(), txn_opts);
assert(txn != nullptr);
txn->SetSnapshot();
// 即使外部的事務(wù)操作是在當(dāng)前事務(wù)操作之前進行更新,這里也會失敗(對setsnapshot 之后所有的操作,當(dāng)前txn都會獨占)
PrintStatus("txn_db->Put", txn_db->Put(WriteOptions(), "key1", "value3"));
PrintStatus("txn->Put", txn->Put("key1", "value1"));
// 樂觀事務(wù) 會在 Commit 的時候失敗
PrintStatus("txn->Commit", txn->Commit());

悲觀事務(wù) DB 和樂觀 事務(wù)DB的差異是 悲觀事務(wù)DB的 在設(shè)置了snapshot之后的check 會在有操作的時候報出來;樂觀事務(wù)DB 則會在 commit 的時候報出來。

1.6 GetForUpdate

有的時候我們 一個事務(wù)內(nèi)部 需要對某一個key 做RMW操作 即 讀改寫,并且保證這個操作是原子的。也就是不能僅僅在寫的時候才獨占這個key,應(yīng)該在讀的時候就需要獨占,才能保證后續(xù)當(dāng)前事務(wù)的寫是原子的。 即讀寫沖突的檢測,Rocksdb 目前僅能通過 GetForUpdate 來進行讀寫沖突的檢測。

這個時候,就需要 GetForUpdate 接口,保證讀的時候就獨占這個key

txn = txn_db->BeginTransaction(write_options);// 當(dāng)前事務(wù) 獨占key1
Status s = txn->GetForUpdate(read_options, “key1”, &value);// 外部事務(wù) 更新 會失敗
s = db->Put(write_options, “key1”, “value0”);

當(dāng)然,對于 悲觀事務(wù)DB 來說 也是提交前就進行沖突檢測,樂觀事務(wù)DB則在 Commit的時候進行沖突檢測。

1.7 RepeatableRead

可重復(fù)讀 的隔離級別 是一個比較重要的操作,用戶希望能一直讀到一個版本之前的數(shù)據(jù) 而不用擔(dān)心這個版本之后的更新產(chǎn)生對結(jié)果的影響。

TransactionOptions txn_opts;
ReadOptions rops;Transaction* txn = txn_db->BeginTransaction(WriteOptions(), txn_opts);
assert(txn != nullptr);
PrintStatus("txn->put", txn->Put("key1", "value2"));
PrintStatus("txn->Commit", txn->Commit());// 開啟設(shè)置snapshot,標(biāo)識后續(xù)該事務(wù) 對所有自己更新的key都是獨占的
txn_opts.set_snapshot = true;
txn = txn_db->BeginTransaction(WriteOptions(), txn_opts);
assert(txn != nullptr);// 在其他事務(wù)更新之前設(shè)置一個snapshot
const Snapshot* snapshot = txn->GetSnapshot();
PrintStatus("txn_db->Put", txn_db->Put(WriteOptions(), "key1", "value3"));// 普通的讀,能夠讀到value3
PrintStatus("txn->Get", txn->Get(rops, "key1", &value));// snapshot 讀,讀到的是value2
rops.snapshot = snapshot;
PrintStatus("txn->Get", txn->Get(rops, "key1", &value));

2. 實現(xiàn)

2.1 WBWI(write batch with index) & WB(write batch)

在看具體事務(wù)實現(xiàn)之前需要先整體了解一下 WB 以及 WBWI,也就是write batch 和 write batch with index 這兩個為 引擎的更新操作提供的組件。

WB 這里不用說太多,使用基礎(chǔ)DB 的時候經(jīng)常能夠用到,Put 這樣的更新接口被調(diào)用后會組織成一個WriteBatch 數(shù)據(jù)結(jié)構(gòu),將多個更新操作合并成一個請求,從而能夠進行原子提交。
事務(wù)DB中,我們使用常見好的事務(wù)DB 直接Put (默認是PermisticDB,也會先構(gòu)造WriteBatch,在commit 的時候進行原子提交)。
這里的WB 數(shù)據(jù)結(jié)構(gòu)形態(tài)大概如下:

整體是一個string-buf,將一個一個k/v請求拼接進去,比較簡單,這里就不過多介紹了。

主要介紹的是 為事務(wù)功能提供的 WBWI,wirte batch with index。其在WriteBatch 基本結(jié)構(gòu)的基礎(chǔ)上構(gòu)造了一個skiplist,用來提供 事務(wù)操作過程中的 read-your-write 以及 savepoint/rollback 等這樣的基本功能。

事務(wù)如果沒有提交,所有的數(shù)據(jù)都還沒有寫入到memtable,都被緩存在WBWI之中。txn->Put 的時候 TryLock 完成之后會去更新WBWI,除了append write-batch 的 string-buffer 之外,會將這個請求在 wb中的offset/cf/key-offset/key-size 這樣的信息形成一個 writeIndexEntry 插入到單獨維護的跳表之中。這個時候,后續(xù)的 txn->Get 就能夠有效得讀到之前寫入但是還沒有提交的請求,其體結(jié)構(gòu)如下:

我們的 txn->SetSavePoint 函數(shù)會將 當(dāng)前 WriteBatchWithIndex 中的信息保存到一個 std::stack<SavePoint, autovector<SavePoint>> stack;,當(dāng)前事務(wù)經(jīng)過若干操作之后 后續(xù)的 txn->RollbackToSavePoint() 會進行彈棧,并將之前保存的狀態(tài)信息更新到現(xiàn)在的WBWI 之中,從而達到事務(wù)的回滾的目的。

SetSavePoint 和 RollbackToSavePoint 函數(shù)的邏輯分別在:void WriteBatch::SetSavePoint() ,WriteBatch::RollbackToSavePoint 之中。

因為WBWI 是在BeginTransaction 的時候構(gòu)造的,所以每一個事務(wù)會有一個自己獨立的WBWI,其內(nèi)部的數(shù)據(jù)結(jié)構(gòu)不需要考慮同步問題。

2.2 PessimisticTransaction 實現(xiàn)

從之前的API 接口測試中,我們能夠知道 PessimisticTransaction 和 OptimisticTransaction 的主要差異是在事務(wù)沖突檢測的時機上,PessimisticTransaction 在事務(wù)有更新操作 或者 GetForUpdatae 的時候就會嘗試進行Key 的獨占,并進行相應(yīng)的沖突檢測。

可看到在 Transaction::Put 的時候會根據(jù)上層配置的transactionDb類型來標(biāo)識應(yīng)該選擇哪一種 TryLock機制,默認是 PessimisticTransaction。TryLock 之后就會更新到 WBWI 之中。

接下來主要看一下 PessimisticTransaction 的 TryLock 是如何實現(xiàn)key 獨占 以及 沖突檢測的。

如果用戶配置了 TransactionOptions::skip_concurrency_control=true 的話,這里后面的key 獨占以及沖突檢測都會直接跳過。
前提是:

  1. 需要應(yīng)用自己保證 不會有key沖突
  2. 需要應(yīng)用保證recovery 的時候所有的回滾和commit 操作 都會新的事務(wù)啟動之前就完成。

這種情況下的性能肯定是最好的, 不過一致性就得自己保證了(應(yīng)用有自己的事務(wù)體系,只用到了Rocksdb的部分事務(wù)能力)。

對輸入的key 的獨占邏輯如下:

PessimisticTransaction::TryLockPessimisticTransactionDB::TryLockPointLockManager::TryLock

比較老的版本 ,最后key 的加鎖過程入口是 TransactionLockMgr::TryLock,這里重構(gòu)成了 PointLockManager::TryLock,主體邏輯都比較接近,主要是通過LockMgr 來實現(xiàn),這里后面會詳細介紹,先關(guān)注主體實現(xiàn)。

到這里當(dāng)前事務(wù)的 當(dāng)前key 的就加鎖成功了,會獨占這個key,直到這個事務(wù) Commit 之前其他的事務(wù)都是無法修改這個key,而其他的事務(wù)在這個事務(wù)獨占成功 但未 提交之前也會進入 上面的TryLock 邏輯之中,會嘗試等待這個 key的鎖釋放,直到超時。

回到 PessimisticTransaction::TryLock 邏輯中,前面的加鎖是為了標(biāo)識這個key 后續(xù)不允許其他事務(wù)的修改。但是如果我們在事務(wù)的一開始就設(shè)置了 txn->SetSnapshot,則當(dāng)前事務(wù)后續(xù)所有的更新操作都會默認獨占。可能有這樣的情況,就是在 SetSnapshot 之后 Put之前 外部事務(wù)可能對這個key 進行了修改并commit,這樣就不滿足Snapshot的語義了(一個事務(wù)設(shè)置snapshot之后 不允許其他事務(wù)的更新),這里當(dāng)前事務(wù)后續(xù)的提交需要失敗才行,PessimisticTransaction::TryLock 后面的邏輯就是為了做一些沖突檢測。

一個簡略的時序圖場景如下:

因為 SetSnapshot 操作需要創(chuàng)建Snapshot 并將這個snapshot 插入到全局的雙向鏈表之中,所以會存在一種可能性就是txn1完成snapshot 之前 txn2 寫入并提交了一個新的更新。這個時候,txn1 繼續(xù) Put的話需要語義上失敗。具體過程就是通過 ValidSnapshot 函數(shù) check txn1 開始時 拿到的最新的 seq 和 現(xiàn)在db 中已經(jīng)提交的最新的seq ,如果小的話txn1 就應(yīng)該失敗。

具體檢查的過程就是 從version 系統(tǒng)中 取一個local_version ,直接暴力遍歷這個version 中的 mem/imm,imm-list/sst ,拿到當(dāng)前沖突key 一個最新的seq即可。
邏輯如下:

PessimisticTransaction::ValidateSnapshotTransactionUtil::CheckKeyForConflictsTransactionUtil::CheckKeyDBImpl::GetLatestSequenceForKeysv->mem->Getsv->imm->Getsv->imm->GetFromHistorysv->current->Get

其中哪一步成功了,就直接返回,不需要后續(xù)的讀了,越靠近上層的key-seq 越新。

做完 ValidateSnapshot ,如果當(dāng)前事務(wù)沖突檢測通過了,則繼續(xù)后續(xù)的 WBWI 的更新即可。

到此,整個 PessimisticTransaction 大體 更新邏輯就是這樣的了。
至于 Get 接口,則是直接從 WBWI 中讀取就好了,調(diào)用 WriteBatchWithIndex::GetFromBatchAndDB 就好了;
還有 GetForUpdate 和 更新的邏輯差不多,也是需要先做完 TryLockValidateSnapshot 的檢測才繼續(xù)后續(xù)的讀取。

需要注意的是 我們在txn->SetSnapshot 之后 外部事務(wù)更新 且 后續(xù)的 txn->Get 是沒有問題的,但是 如果讀取使用的是 GetForUpdate ,則會檢測 read-write confict ,GetForUpdate 會失敗;它要求的一致性語義 和 write-write confict 要求的是一樣的。

2.3 LockManager 以及 DeadLock detect 實現(xiàn)

2.3.1 LockManager 加鎖實現(xiàn)

在 PessimisticTransaction 的 TryLock 底層,我們會發(fā)現(xiàn)當(dāng)前事務(wù)想要給 key加鎖(保證 commit 之前對key 的獨占語義 )是通過 LockManager 實現(xiàn)的,接下來仔細看一下這個組件的實現(xiàn)原理,以及其如何進行死鎖檢測的。

后文描述的 OptimisticTransaction 事務(wù) 因為 TryLock 過程不需要檢測鎖沖突,所以不需要用到LockManager.

LockManager 組件結(jié)構(gòu)大概如下:

在整個DB 內(nèi)部維護了一個大的 LockMaps,它是一個 column family id 到 LockMap的一個 unodered_map。這個DB內(nèi)部的每一個 cf 都有一個自己的LockMap。

// Map of ColumnFamilyId to locked key info
using LockMaps = std::unordered_map<uint32_t, std::shared_ptr<LockMap>>;
LockMaps lock_maps_;

LockMap 內(nèi)部 默認會有16個(可以通過 TransactionDBOptions::num_stripes進行配置) LockMapStripe,根據(jù)要加鎖的Key 的hash值,會映射到對應(yīng)的LockMapStripe,這里的目的應(yīng)該將輸入的key 打散到不同的stripe中,防止一個stripe 膨脹過大。
每一個 Stripe 內(nèi)部有三個數(shù)據(jù)結(jié)構(gòu),stripe粒度的 mutex 和 conditionvariable,還有一個最重要的 unordered_map,用來保存 不同的key的 LockInfo,lock_info 中會用數(shù)組存儲 操作當(dāng)前key的 transactionId 以及 transaction experation_time,用來進行加鎖相關(guān)的判斷。

struct LockInfo {bool exclusive;autovector<TransactionID> txn_ids;// Transaction locks are not valid after this time in usuint64_t expiration_time;...
};

針對一個輸入的key,具體的加鎖過程如下:

  1. 拿到當(dāng)前線程緩存的 lock_maps_cache_,它是一個ThreadLocalPtr(線程性能加速),從中 根據(jù)ColumnFamily ID 找到對應(yīng)的LockMap; 如果 lock_maps_cache_ 沒有, 則從全局的 LockMaps 查找,找到則添加到 lock_maps_cache_
    關(guān)于ThreadLocalPtr的介紹可以查看 rocksdb 讀寫鏈路上的極致優(yōu)化。

  2. 根據(jù) 輸入Key 的Hash,從上一步中拿到的LockMap 中取出 key 被映射到的 LockMapStripe,并對該 Stripe 加鎖(后續(xù)的處理中可能涉及對 stripe 內(nèi)部 unordered_map keys 的更新)同時用 txn->GetID(), txn->GetExpirationTime() 構(gòu)造一個LockInfo

  3. 帶著這個LockInfo 先判斷這個key 所在的 LockMapStripe 的 keys 中是否有這個key,有則說明之前已經(jīng)加過鎖,取出這個 key 在 keys 中 的lockinfo :如果用戶只允許一個key 加鎖 ,即key 的LockInfo 是獨占鎖,且已有的lockinfo已經(jīng)超時,這里 則替換成 傳入的 LockInfo;如果用戶允許多個事務(wù) 搶占當(dāng)前key 的鎖,會將這個事務(wù)ID 添加到 wait-ids 數(shù)組,等待加鎖;

    如果 LockMapStripe 的 keys 中沒有這個key,則將當(dāng)前key 以及 傳入的LockInfo 添加到keys 對應(yīng)的 unordered_map 之中。

    需要注意的是這里有一個 stripe 允許的最大 加鎖key 的數(shù)量判斷(構(gòu)造 LockManager 的時候 通過TransactionDBOptions::max_num_locks 控制,默認是不進行限制的),超過這個限制同樣加鎖失敗。

  4. 如果第三步 還是加鎖失敗, 到第四步 會進入一個 大的超時循環(huán)中,在這個循環(huán)中會等待加鎖,等待的超時時間是逐 key 對應(yīng)的LockInfo 中的超時時間,如果等待的時間過了超時時間,當(dāng)前事務(wù)就會加鎖失敗返回,每一個 txn 都會進入到這個 循環(huán)中進行。

2.3.2 DeadLock 檢測實現(xiàn)

在上面的第四步中,因為每一個嘗試加鎖的 txn 在第一次沒有獲取到鎖的時候 都會進入到 大循環(huán)中等待獲得鎖,這里并發(fā)事務(wù)場景下可能會出現(xiàn)死鎖問題,所有會有死鎖檢測機制,實現(xiàn)邏輯是在 PointLockManager::IncrementWaiters 之中。

這里涉及到 死鎖檢測的幾個參數(shù)如下:

  • TransactionOptions::deadlock_detect 是否開啟死鎖檢測,開啟則會進行
  • TransactionOptions::deadlock_detect_depth 因為維護的是一個 txn 圖,這里會有死鎖檢測的深度設(shè)置,越深肯定消耗的CPU計算越多

死鎖檢測的核心是想要在一個 有向無環(huán)圖 中檢測 有沒有 wait-circle,即類似如下圖:

上圖中通過尖頭標(biāo)識依賴,A–>C,txn A想要獲得鎖必須等到 txn C 釋放才能獲得。
顯然這個 wait-circle 是不會死鎖的, 只要 txn C 能夠釋放,那么其他的事務(wù)就能繼續(xù)推進,但是調(diào)整一下C的依賴可能就會死鎖了。

這樣的依賴圖 中出現(xiàn)了環(huán),E–>A, A–>C, C–>E ,那就會死鎖了。

所以,我們的死鎖檢測就是拿著當(dāng)前事務(wù)前面嘗試獲取鎖時 得到的一個 wait-ids 數(shù)組 和已有的wait-circle 來構(gòu)建一個 有向無環(huán)圖,在這個 有向無環(huán)圖中 按照 前面用戶配置的 depth 進行 wait-circle 的檢測。

知道了核心目的,這里的代碼邏輯就很簡單了:
死鎖檢測入口是在PointLockManager::IncrementWaiters里面,通過前面對當(dāng)前 txn 構(gòu)造好的 wait-ids 數(shù)組構(gòu)造 wait_txn_map_rev_wait_txn_map_ 兩個 HashMap。

  • rev_wait_txn_map_ 用來保存 活躍事務(wù) 和 該事務(wù)在 有向無環(huán)圖中的節(jié)點個數(shù)(也可以理解為權(quán)重)
  • wait_txn_map_ 用來保存整個活躍事務(wù)視圖,用于 廣度優(yōu)先遍歷。保存的內(nèi)容是 當(dāng)前事務(wù) 和 該事務(wù)有關(guān)聯(lián)的事務(wù)信息TrackedTrxInfo

接下來就是經(jīng)典的廣度優(yōu)先遍歷的實現(xiàn)了,通過提前resize 好的兩個vector queue_valuesqueue_parents ,resize的大小是 前面說的 deadlock_detect_depth。 queue_values 保存層序,即每一層的所有節(jié)點;queue_parents 用來記錄當(dāng)前層的父節(jié)點的下標(biāo),方便后面在發(fā)現(xiàn)死鎖環(huán)之后 進行死鎖路徑的回溯。

詳細的算法實現(xiàn)這里就不細講了,廣度優(yōu)先算法而已。

結(jié)束條件是:

  1. deadlock_detect_depth 這個檢測深度下如果沒有發(fā)現(xiàn) 當(dāng)前事務(wù)id 和 已有活躍事務(wù)依賴圖 中不會有相等的情況,則認為不會死鎖,返回未發(fā)現(xiàn)死鎖。
  2. 如果發(fā)現(xiàn)有相等的,也就是在依賴圖 下找到了環(huán)的存在,則通過 queue_parents 數(shù)組來回溯當(dāng)前事務(wù)在依賴圖中的依賴路徑,保存到 dlock_buffer_ 中,同時將該事務(wù)信息 從 事務(wù)依賴圖中 踢出 DecrementWaitersImpl,也就是將 當(dāng)前txn 的 wait-ids 逆著走一遍初始化的過程,返回發(fā)現(xiàn)死鎖。

因為死鎖檢測到的準(zhǔn)確度與 deadlock_detect_depth 配置有關(guān)系,如果上層的事務(wù)并發(fā)很大,想要有效避免死鎖問題,就需要合理得配置這個選項了,當(dāng)然也需要和性能做一個trade-off,依賴圖很大,深度又很深的話,那一次 Trylock 操作的開銷可就不可忽視了。

這里實現(xiàn)上有一個細節(jié),存儲 事務(wù)的依賴圖 rocksdb 并沒有選擇 std 的 unordered_map,而是自己利用 std::arryaautovector(rocksdb 自己的用于小數(shù)據(jù)存儲的vector, 減少擴容 以及 添加元素時 產(chǎn)生的內(nèi)存分配的開銷,開始時直接resize了一個大小) 實現(xiàn)了一個簡易的 HashMap
原因是 std::unordered_map 在 每一次 插入 或者 刪除元素的時候 由于需要維護 iterator 的有效性(紅黑樹需要調(diào)整父子節(jié)點的指針鏈接關(guān)系),需要進行內(nèi)存的分配和釋放,這在 TryLock 中 尤其是高并發(fā)下,會造成不必要的開銷。
所以,這里還是選擇用 array + autovector,array 作為hash-bucket,autovector 存儲每一個bucket內(nèi)部的元素即可。

2.4 OptimisticTransaction

接下來看一下 OptimisticTransaction 的實現(xiàn),相對來說就簡單很多了, 相比于 PessimisticTransaction 的主要差異就是 沖突檢測的時機 是在 Commit 階段才進行。
它在 TryLock 的時候 會將當(dāng)前 要更新的 key的信息添加到 LockTracker 中:

要追蹤的信息主要包括當(dāng)前key的 cf, seq, 是否只讀,是否是獨占的;其中 seq 是取用戶設(shè)置的snapshot(如果設(shè)置了的話)的 seq,如果沒有設(shè)置,則直接從basedb 中取最新的。

這里 LockTracker 結(jié)構(gòu)大概是這樣的:

為每一個cf 維護一個 TrackedKeyInfos 的unordered_map,其中保存這個cf 追蹤的key 以及 其 TrackedKeyInfo信息。

接下來 看看 Commit 的時候 樂觀事務(wù)DB 怎么做沖突檢測,按照經(jīng)驗,看上面記錄的信息,肯定是 seq 是沖突檢測的核心了。
Commit 的代碼中提供了兩種 Occ (optimistic concurrent control)策略: kValidateParallelkValidateSerial ,在2020.6 月份及以前的版本 應(yīng)該是只有一種 occ 策略,也就是 kValidateSerial 的實現(xiàn)。

先來分別看一下兩種實現(xiàn)的具體差異,再想想為什么分別會有這兩種策略,希望能為我們在分布式事務(wù)的設(shè)計中提供一些借鑒思路。

2.4.1 kValidateSerial occ

實現(xiàn)入口是在 OptimisticTransaction::CommitWithSerialValidate

直接拿到 basedb,調(diào)用 WriteWithCallback 函數(shù),其中 callback 的實現(xiàn)是 OptimisticTransactionCallback::Callback,也就是 OptimisticTransaction::CheckTransactionForConflicts
WriteWithCallback 會在每次寫入之前對所有要寫入的請求執(zhí)行 callback,WriteImplwriter->CheckCallback(this),檢測是否滿足寫入的要求。

CheckTransactionForConflicts 中做的事情,就是拿著 前面 TryLock 過程中獲取到的 LockTracker 信息 進行seq num的比較,和 PessimisticTransaction 事務(wù)中的 ValidSnapshot 做的事情一樣,檢測 tracker 中要提交的key 的 seq 是否比當(dāng)前db 中最新的 已經(jīng)commit 的 seq小,用來確定這個事務(wù)執(zhí)行 中間是否有外部事務(wù) 對當(dāng)前key 的更新(完成 commit的操作)。

	TransactionUtil::CheckKeyForConflictsTransactionUtil::CheckKeyDBImpl::GetLatestSequenceForKeysv->mem->Getsv->imm->Getsv->imm->GetFromHistorysv->current->Get

如果做完沖突檢測,這一批事務(wù)的 tracker key都沒有問題,則可以提交,繼續(xù)后續(xù)的寫入(寫WAL),否則會返回失敗。

occ 策略中的 另一個策略在沖突檢測這里都是差不多的。

2.4.2 kValidateParallel occ

這個策略的入口是 OptimisticTransaction::CommitWithParallelValidate
關(guān)于沖突檢測的內(nèi)部實現(xiàn)就不過多介紹了,都是一樣的,主要是這個策略如何調(diào)度 沖突檢測的。

在寫入之前 會先對所有的 tracked_locks_ 中的多事務(wù)的 key 按照順序進行加鎖,然后統(tǒng)一進行 多事務(wù)的沖突檢測,沖突檢測通過之后直接調(diào)度寫入。

這里有一個 issue 來簡單描述了 推出 kValidateParallel occ 策略的原因: kValidateSerial 太慢了。
雖然 optimisticTransaction 是建議 事務(wù)沖突概率較小的場景下才用,但是正常的多cf 寫入的時候有人發(fā)現(xiàn)它比 baseDb和 permisticDB 慢了 5倍,看起來像是很多CPU 沒有被利用起來的樣子。
原因是因為 舊版本的實現(xiàn) 也就是 kValidateSerial 策略中:

  1. OptimisticTransactionCallback::AllowWriteBatching 返回是false,也就是在 不會調(diào)度 rocksdb 的寫模型中 的 leader writer 批量寫其他 writer的請求,這樣的話大量的并發(fā)就沒有什么用了, 都是順序?qū)憌al。
  2. OptimisticTransaction 本身就是在 commit 階段進行沖突檢測,所以 寫入之前會有一些額外的CPU消耗(拿沖突key 的最新seq的過程 需要從上到下掃LSM-tree,直到拿到當(dāng)前key在basedb 最新提交的seq)

這一些過程導(dǎo)致 在 舊版本的實現(xiàn)中 性能最差(即使是正常的請求處理),主要影響還是在 利用 Callback 去做沖突檢測的過程為了保證沖突檢測的有效性而關(guān)閉 group commit 功能。

所以,新的版本 主要就是解決這個問題,將callback 去掉,挪到了 write之前,畢竟沖突檢測不論什么時候都得做,而挪到寫鏈路之前做 并不會影響group-commit 的邏輯,沖突檢測通過之后還是正常的 寫邏輯。

相關(guān)的issue和pr 可以參考:
https://github.com/facebook/rocksdb/issues/4402
https://github.com/facebook/rocksdb/pull/6240

occ 策略希望能用一種樂觀的方式處理并發(fā)事務(wù)場景,雖然在高并發(fā)的低沖突事務(wù)處理下優(yōu)勢明顯,但是在正常的事務(wù)處理邏輯中不應(yīng)該有更多的性能損耗, 可能是因為使用場景較少的原因,這個性能問題才在18年提出 20年才修復(fù)。

3. 總結(jié)

限于篇幅原因,本來還想繼續(xù)展開 為myrocks 提供的 2PC 和 為 PessimisticTransactionDB 所做的長事務(wù)內(nèi)存優(yōu)化的 WritePreparedTxnDB 以及 WriteUnPreparedTxnDB ,先暫時推后吧。

總的來說,通過Rocksdb 的完整 事務(wù)實現(xiàn)過程 我們能夠大體了解到 基本隔離級別的實現(xiàn) 以及 事務(wù)并發(fā)場景時 read-write confict 和 write-write conflict 的有效解決方案。因為 Rocksdb 是引擎底座,這一些實現(xiàn)方案 以及 底層的代碼細節(jié)都是經(jīng)過工業(yè)界長期驗證的,值得學(xué)習(xí)參考。


不出意外應(yīng)該是今年的最后一篇博客了,后面幾天會寫一寫年末總結(jié),為這 “多災(zāi)多難” 的一年畫一個句號了。

總結(jié)

以上是生活随笔為你收集整理的Rocksdb的事务(二):完整事务体系的 详细实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

国产亚洲精品女人久久久久久 | 狠狠干夜夜操天天爽 | 超碰在线个人 | 欧美精品一区在线 | 欧美日韩视频网站 | 亚洲另类人人澡 | 欧美一区二区三区激情视频 | 免费激情在线电影 | av在线网站大全 | 超碰在线97国产 | 一区二区在线不卡 | 久久人人爽人人爽人人片av软件 | 久久久久国产精品免费 | 国产精品一区二区三区久久 | www.精选视频.com | 亚洲狠狠操 | 久久精品久久精品久久精品 | 亚洲2019精品 | 免费在线h| 久久久91精品国产一区二区精品 | 亚洲人片在线观看 | 欧美在线观看小视频 | 国产精品久久久久av免费 | 亚洲欧美视频在线 | 国产专区精品视频 | 亚洲精品男人天堂 | 午夜精品久久久久久久久久久久 | 91av在线免费视频 | 三日本三级少妇三级99 | 99精品视频在线观看视频 | 99 视频 高清 | 91网站免费观看 | 久久在线免费 | 欧美a性| 1024手机在线看 | 在线а√天堂中文官网 | 日韩精品一区二区三区水蜜桃 | 天天操综合网站 | 麻豆 free xxxx movies hd | 亚洲午夜久久久久久久久久久 | 国产在线视频资源 | 免费在线国产黄色 | 91中文字幕在线 | 天天色天| 精品国产一区二区三区男人吃奶 | 国产精品一区二区三区免费看 | 狠狠操精品 | 综合久久久久久久 | 日色在线视频 | 成人午夜精品福利免费 | 精品欧美小视频在线观看 | 这里只有精彩视频 | 久久线视频 | 精品视频区 | 国产精品久久久久久久久久白浆 | 一级黄色a视频 | 五月天国产 | 欧美日韩中 | 久久综合久久久久88 | www.色午夜 | 久久久久久国产精品久久 | 亚洲成av人影院 | 又大又硬又黄又爽视频在线观看 | 婷婷狠狠操 | www.人人干 | 欧美va在线观看 | 91成人在线观看高潮 | www国产在线 | 亚洲片在线 | 色网站黄 | 久久99精品国产麻豆宅宅 | 久久久久亚洲天堂 | 国产日韩精品视频 | 免费成人在线电影 | 中文字幕婷婷 | 亚洲日本中文字幕在线观看 | 免费在线播放视频 | 色综合五月 | 91视视频在线直接观看在线看网页在线看 | 日韩久久一区二区 | 日本精品一区二区三区在线播放视频 | 天堂av在线免费观看 | 亚洲 综合 国产 精品 | 亚洲综合在线五月 | 99视频在线精品 | 五月花丁香婷婷 | 美女在线免费观看视频 | 国产99久久久欧美黑人 | 国内精品毛片 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 2022久久国产露脸精品国产 | 四虎在线免费视频 | 不卡的av电影 | 人人澡人人澡人人 | 九九涩涩av台湾日本热热 | 天天操天天操天天操天天操天天操天天操 | 少妇bbw搡bbbb搡bbb | 999国内精品永久免费视频 | 夜夜视频 | 色综合中文字幕 | 色五月色开心色婷婷色丁香 | 亚洲精品视频在线 | 精品久久1 | 亚洲精品久 | 国产又粗又猛又爽又黄的视频免费 | 人人澡人人模 | 久草观看 | av片中文 | 国产精品成人一区二区三区吃奶 | 日韩欧美综合在线视频 | 日韩精品观看 | 伊人狠狠色 | 精品影院一区二区久久久 | 亚洲综合成人专区片 | 国产一级精品在线观看 | 国产亚洲精品福利 | av短片在线 | 日本少妇高清做爰视频 | 亚洲激情六月 | 成人在线观看你懂的 | 天天躁日日 | 丰满少妇久久久 | 激情影院在线观看 | 欧美一级久久久久 | 国产成人av电影 | 久久亚洲私人国产精品 | 中国一级片在线 | 亚洲精品美女视频 | 国产日产精品一区二区三区四区 | 最新国产精品久久精品 | 手机av在线免费观看 | 97成人免费 | 最近中文字幕在线中文高清版 | 亚洲自拍偷拍色图 | 九九九电影免费看 | 可以免费观看的av片 | 91尤物国产尤物福利在线播放 | 日韩精品久久久久久久电影竹菊 | 色综合天天视频在线观看 | 人人狠狠综合久久亚洲 | 超碰国产97 | 亚洲一级黄色片 | 中国成人一区 | 精品日韩在线 | 国产成人高清在线 | 亚洲码国产日韩欧美高潮在线播放 | 丁香久久综合 | 亚洲国产综合在线 | av中文字幕免费在线观看 | av动图| 福利视频导航网址 | 欧美日韩一级久久久久久免费看 | 狠狠干网址 | 一级片在线 | 国内精品久久久久国产 | 天天爱天天色 | 国偷自产中文字幕亚洲手机在线 | 国产成人精品综合久久久久99 | 精品国产一区二区三区久久久久久 | 国内精品久久久久影院一蜜桃 | 国产日韩精品一区二区三区在线 | 永久免费精品视频网站 | 久久精品伊人 | 亚洲精品美女在线观看 | 91精品国产成人 | 国产色在线视频 | 日日操天天操夜夜操 | 国产激情电影综合在线看 | 99久久婷婷国产一区二区三区 | 精品一区精品二区 | 天天干天天操天天做 | 日韩在线观看三区 | 久久在线影院 | 亚洲日本中文字幕在线观看 | 91中文在线视频 | 日韩动漫免费观看高清完整版在线观看 | 五月婷婷免费 | 国产欧美久久久精品影院 | 国产精品毛片久久蜜 | 国产高清黄色 | 欧美日韩高清一区 | 中文字幕精品在线 | 91成版人在线观看入口 | 精品欧美乱码久久久久久 | a黄色片在线观看 | 亚洲精品字幕在线 | 国产原创av在线 | 人人澡澡人人 | 国产高清在线观看av | 国产精品99久久久久的智能播放 | 国产女人18毛片水真多18精品 | av黄色成人| 丁香久久久 | 日韩成人免费电影 | 国产黄色资源 | 日本99久久 | 久操久| 五月婷婷电影网 | 懂色av一区二区在线播放 | 国产精品第十页 | 成人免费电影 | 午夜在线观看一区 | 欧美极品少妇xbxb性爽爽视频 | 色噜噜在线观看视频 | 91高清免费 | 91麻豆产精品久久久久久 | 久久亚洲影视 | 国产精品夜夜夜一区二区三区尤 | 国产一区二区高清不卡 | 91福利社在线观看 | 欧美日韩视频在线 | 国产精品久久电影网 | 国产高清视频在线播放 | 久久免费视频在线观看 | 操操爽 | 日韩高清一区二区 | 中文字幕免费播放 | 91九色国产视频 | a√国产免费a | 中文字幕91在线 | 丝袜美腿亚洲 | 久久久久久久看片 | 免费看的av片 | 亚洲视屏在线播放 | 一区二区三区在线观看免费 | 日韩午夜高清 | 国产精品2019 | 久久久久国产精品免费网站 | 精品国产一区二区三区四区vr | 一区二区视频在线免费观看 | 午夜在线观看一区 | 国产中文字幕在线观看 | 超碰在线个人 | 欧美-第1页-屁屁影院 | 91免费的视频在线播放 | 五月天天av| 欧美成人区 | 日韩色中色 | 四虎成人精品在永久免费 | 久草精品视频在线观看 | av福利电影 | 国产精品igao视频网入口 | 免费欧美高清视频 | 91看片在线免费观看 | 日日夜夜天天久久 | 国产一区二区在线看 | 91私密视频| 韩国精品福利一区二区三区 | 91麻豆精品国产91久久久使用方法 | 黄色国产精品 | 1区2区3区在线观看 三级动图 | 狠狠色丁香婷婷综合久小说久 | 久久久免费精品视频 | 91传媒视频在线观看 | 国产69精品久久久久久久久久 | 亚洲最大的av网站 | 97在线超碰 | 国产精品精品久久久久久 | www.香蕉视频在线观看 | 黄污视频网站 | 中文字幕电影在线 | 丁香五月亚洲综合在线 | 色中文字幕在线观看 | 国产精品高 | 亚洲视频免费视频 | 欧洲精品一区二区 | 欧美性黄网官网 | 91麻豆精品国产自产在线游戏 | 在线 高清 中文字幕 | 国产精品毛片一区二区在线看 | 成人在线视频观看 | 天天做天天射 | 欧美一区免费观看 | 在线观看一区二区精品 | 久久久国产精品人人片99精片欧美一 | 欧美成人黄 | 天天综合在线观看 | 亚洲在线a| 在线观看的a站 | 97超碰人人 | 91在线91拍拍在线91 | 精品欧美一区二区在线观看 | 国产精品视频免费看 | 丁香色天天 | 五月婷婷电影网 | 中文字幕乱偷在线 | 婷婷色综合 | 91大神在线观看视频 | 天堂av影院 | 青青草国产精品 | 天天爱天天射 | 久久理论视频 | 国产精品成人一区二区三区 | 国产呻吟在线 | 久久爱导航 | 亚洲精品成人 | 国产97在线看 | 中文字幕在线精品 | 日韩视频免费在线 | 在线免费观看av网站 | 久久观看免费视频 | av成人免费在线 | 国产又粗又长又硬免费视频 | 久久99九九99精品 | 久久精品看 | 91成人网页版 | 97国产精品免费 | 黄色精品在线看 | 黄色在线视频网址 | 丁香六月av| 黄色片网站av | 99在线视频播放 | 美国人与动物xxxx | 成人精品电影 | 国产精品一级视频 | 98涩涩国产露脸精品国产网 | 婷婷五综合 | av丝袜美腿| 色婷婷伊人 | 成人亚洲欧美 | 午夜精品中文字幕 | 在线视频 成人 | 我要色综合天天 | 黄色三级网站在线观看 | 亚洲综合成人在线 | 久久精品欧美日韩精品 | 精品视频123区在线观看 | 婷婷看片 | 91高清视频在线 | 久久人人爽人人爽人人片 | 日韩最新在线视频 | 天天干天天操天天拍 | 国产一区二区久久久久 | 7799av| 中文字幕大全 | 91漂亮少妇露脸在线播放 | 色黄久久久久久 | 黄色小说视频网站 | 四虎影视久久久 | 天堂av影院 | 91在线视频观看免费 | 国产精品入口传媒 | 久久久精品在线观看 | 人人澡人人澡人人 | 黄色片视频在线观看 | 亚洲欧洲美洲av | 天天干天天射天天爽 | 国产999精品久久久久久麻豆 | 成人久久精品 | 91在线91| 一级性生活片 | 国产呻吟在线 | 久久99国产精品二区护士 | 黄色在线观看免费网站 | 国产精品99在线观看 | 最近中文字幕第一页 | 日日摸日日添日日躁av | 一级理论片在线观看 | 亚洲首页| 久久精品这里都是精品 | 日韩免费观看一区二区 | 亚洲国产欧美在线人成大黄瓜 | 亚洲电影网站 | 成人免费观看网址 | 国产一区视频在线 | 国产精品久久久久久久久免费看 | 国产96精品| 亚洲成熟女人毛片在线 | 超碰人人在线观看 | 丁香视频在线观看 | 国产精品国产自产拍高清av | 欧美精品九九 | 91av网站在线观看 | 国产手机视频在线 | 久久麻豆视频 | 免费黄色在线网站 | 国产在线黄 | 亚洲精品www久久久 www国产精品com | 成年人在线观看免费视频 | 999成人网 | 日韩www在线 | 久久综合亚洲鲁鲁五月久久 | 在线亚洲高清视频 | 精品产品国产在线不卡 | 偷拍精偷拍精品欧洲亚洲网站 | 久久久国产毛片 | 中文字幕视频网 | 激情在线网址 | 久久超 | 欧美做受69| 嫩草av在线| 久草在线高清视频 | 日批在线观看 | 天天天天综合 | 亚洲成人资源 | 天天操天天操天天操天天操天天操天天操 | www.99av| 99热最新精品 | 日韩色区 | 亚洲天堂色婷婷 | 91精品爽啪蜜夜国产在线播放 | 一区二区视频电影在线观看 | 午夜精品久久久久久久久久久久久久 | 欧美三级高清 | 国产免费不卡 | 在线国产激情视频 | 亚洲国产日韩一区 | 在线视频 国产 日韩 | www.亚洲黄色| 日韩激情小视频 | 日韩一区二区三区高清在线观看 | 在线之家免费在线观看电影 | 一区二区三区在线视频111 | 亚洲精品在线视频 | 久久99网站 | 天天操天天操天天操 | 日日躁夜夜躁xxxxaaaa | 超碰免费在线公开 | 西西444www大胆无视频 | 六月天综合网 | 亚洲精品国产视频 | 在线观看亚洲精品 | 99久久影院 | 国产精品欧美在线 | 成年人电影免费在线观看 | 一级理论片在线观看 | 久久婷婷精品视频 | 国产精品99久久久久人中文网介绍 | 亚洲国产资源 | 在线观看黄色大片 | 亚洲精品免费在线观看 | 欧美精品三级在线观看 | 四虎在线视频 | 91麻豆福利 | 国内揄拍国产精品 | av天天澡天天爽天天av | 一区二区三区四区影院 | 夜夜躁日日躁 | 中文字幕av免费观看 | 日韩欧美成 | 在线观看免费高清视频大全追剧 | 国产精品久免费的黄网站 | 欧美色久 | 国产69久久久 | 黄色aaa毛片 | 在线观看黄色国产 | 精品日本视频 | 伊人午夜视频 | 天天色天天艹 | 日韩国产欧美在线视频 | 91久久奴性调教 | 精品视频在线免费 | 国产二区电影 | 日日噜噜噜噜夜夜爽亚洲精品 | 在线看片中文字幕 | 中文字幕在线影院 | 久久久www免费电影网 | 国产精品乱码久久久 | 久久国产精品免费视频 | 婷婷色站| 99热这里是精品 | 黄色一级大片在线免费看产 | 亚洲国内精品 | 免费99精品国产自在在线 | 激情黄色一级片 | 又黄又爽又刺激的视频 | 欧美天堂久久 | 免费观看性生交 | 亚洲无吗视频在线 | 国产精品成人av电影 | 日韩免费高清在线观看 | 欧美日韩电影在线播放 | 69xxxx欧美 | 97国产超碰在线 | 天天色天天色天天色 | 欧美大香线蕉线伊人久久 | 国产在线观看免费 | 91桃花视频 | 久久曰视频 | 久久综合五月天婷婷伊人 | 久久99免费| 国产成人精品999 | 国产99久 | 中文字幕免费高清 | 国产欧美精品在线观看 | 久久免费视频播放 | 久久久久国产精品午夜一区 | 99在线精品视频在线观看 | 久久99国产综合精品 | 四虎国产视频 | 色香天天 | 久久a v视频 | 久久97久久97精品免视看 | 在线观看精品一区 | 中文字幕黄色网 | 日韩视频在线不卡 | 日韩二区三区 | 亚洲天堂网站 | 亚洲精品午夜aaa久久久 | 国内精品久久久久国产 | 91av短视频| 日韩精品一区不卡 | 爱干视频 | 国产精选视频 | 91传媒免费在线观看 | 中文字幕在线视频精品 | 日日夜夜爱 | 天天骚夜夜操 | 国内免费久久久久久久久久久 | 在线亚洲激情 | 久草在线视频在线 | 日韩精品免费一区 | 黄色三级免费观看 | 日韩欧美电影 | 蜜臀av性久久久久av蜜臀妖精 | 日本动漫做毛片一区二区 | 国产99久久 | 色多多污污在线观看 | 亚洲涩涩色 | 成人久久久电影 | 操操操com | 人人爽人人爽人人片av免 | 国产精品美女www爽爽爽视频 | 亚洲欧美日韩国产一区二区三区 | 国产视频欧美视频 | 中文在线中文a | 欧美精品久久久久a | 国产精品mm | 黄色电影网站在线观看 | 免费黄色网止 | 97在线精品视频 | 国内精品久久久久影院优 | 六月丁香婷婷久久 | 久久久一本精品99久久精品 | 99c视频在线 | 91刺激视频 | 激情 一区二区 | 国产精品一区二区电影 | 精品久久久久久久久久国产 | 国产男女爽爽爽免费视频 | 69av网| 国产精品美女免费视频 | 亚洲一区久久 | 一级国产视频 | 亚洲国产色一区 | 国产黄色电影 | 99在线免费观看 | 手机av看片 | 久草免费在线观看 | 91精品视频在线观看免费 | 91福利视频免费 | 国产高清免费在线播放 | 成人久久毛片 | 欧美一区二区日韩一区二区 | 日韩欧美高清 | 一个色综合网站 | 亚洲理论在线观看 | 国产无套精品久久久久久 | 欧美精品免费在线 | 久久成人国产精品 | 麻豆传媒精品 | 综合天天色 | 黄色免费在线视频 | 97免费 | 在线观看免费观看在线91 | 亚洲最大免费成人网 | 国产精品免费观看视频 | 黄色毛片视频 | 久久久www成人免费毛片 | 亚州欧美视频 | 五月精品 | 亚洲黄色在线观看 | 亚洲国产精品久久久久 | 91在线网址| 你操综合 | 久久精品看 | 国外av在线 | 日韩免费一区 | 久久免费电影网 | 丁香婷婷综合激情 | 亚洲精品一区二区三区四区高清 | 在线精品视频免费播放 | 久久婷婷开心 | 天堂黄色片 | 婷婷性综合 | 久久99国产精品免费网站 | 久久黄网站 | 国产一及片 | 精品福利视频在线观看 | 国产免费不卡av | 日韩精品免费一区二区 | 992tv人人网tv亚洲精品 | 久久人人爽人人爽人人片av免费 | 97手机电影网 | 三级小视频在线观看 | 亚洲黄色软件 | 黄色软件视频网站 | 天天综合亚洲 | 亚洲精品理论 | 精品国产一区二区三区四区vr | 日韩美精品视频 | 色综合天天干 | 69av网| 久久久久久久久亚洲精品 | 伊人影院av | 日韩欧美区 | 视频在线播放国产 | 九九一级片 | 在线不卡中文字幕播放 | 精品视频久久久久久 | 有码中文在线 | 久久99精品久久久久久久久久久久 | 色综合久久久久久中文网 | 涩涩成人在线 | 亚洲视频精品 | 日韩日韩日韩日韩 | 久久综合久久综合久久 | 午夜精品福利一区二区三区蜜桃 | 日韩福利在线观看 | 正在播放国产91 | 久久av影院 | www.狠狠干| 在线观看精品 | 欧美伦理一区 | 天天干夜夜夜 | av观看久久久 | 亚洲精品视频一二三 | 香蕉视频在线免费看 | 日韩一区二区三区视频在线 | 少妇bbb好爽 | 久久久久女教师免费一区 | 亚洲最大av网站 | 日韩在线欧美在线 | 午夜av在线电影 | 亚洲视频 中文字幕 | 久久看看 | 伊人婷婷激情 | 中文字幕麻豆 | 亚洲精品在线免费 | 久久国产精品免费一区二区三区 | 欧美了一区在线观看 | 一区二区理论片 | 欧美淫视频 | av片在线观看 | 成人精品一区二区三区中文字幕 | 欧美一区二区在线刺激视频 | 激情五月播播久久久精品 | 久久久久一区二区三区 | 玖玖视频精品 | 一级黄色在线免费观看 | 日日夜夜爱 | 综合久久精品 | 天天躁天天躁天天躁婷 | 最近最新中文字幕视频 | 久久婷婷一区二区三区 | 激情五月综合网 | 麻豆播放 | 91成人免费看片 | 91精品婷婷国产综合久久蝌蚪 | 国产高清在线观看av | 欧美成人xxxxxxxx | 97看片吧 | 久久免费高清视频 | 午夜私人影院久久久久 | 激情网在线观看 | 国产一级二级视频 | 国产精品av久久久久久无 | 久久国产精品小视频 | 超碰公开在线 | 黄网站色| 亚洲午夜激情网 | 欧美一区成人 | 在线观看亚洲精品视频 | av手机版 | 久久精品99久久 | 免费在线观看成年人视频 | 911香蕉视频| 成人在线观看你懂的 | 爱色av.com | 日韩欧美一区二区三区在线观看 | 激情五月婷婷综合网 | 在线观看的黄色 | 精品免费一区二区三区 | 国产精品成人久久久久久久 | 日韩在线观看电影 | 久久人人97超碰精品888 | 天天久久夜夜 | 国产剧情在线一区 | 欧美日韩高清一区二区 | 麻豆精品传媒视频 | 欧美亚洲一区二区在线 | 国产三级精品在线 | 国产成人久久精品 | 国产精品免费观看国产网曝瓜 | 亚洲国产黄色片 | 91亚洲欧美 | 亚洲视频国产 | 天天操夜夜操 | 日韩在线观看一区二区 | 在线免费色视频 | 日本中文字幕视频 | 中文字幕永久 | 99精品免费 | 亚洲精品视频观看 | 中文字幕 国产视频 | 亚洲涩涩涩涩涩涩 | 日韩免费看 | 欧美一级看片 | 天天色.com | 国产一级一片免费播放放 | 狠狠操狠狠干天天操 | 一本一本久久a久久精品牛牛影视 | 麻豆视频免费观看 | 久久艹人人 | 国产日韩欧美在线 | 成人在线免费小视频 | 国产一区二区三区久久久 | 一区二区激情 | 亚洲永久在线 | 五月婷婷天堂 | 久久视频在线视频 | 精品一区电影国产 | www.五月激情.com | 色婷婷视频在线 | 国产黄a三级| 天天操天天吃 | 国产精品区免费视频 | 久久一区二区三区超碰国产精品 | 久久精品免费看 | 狠狠操狠狠 | 中中文字幕av | 久久久影视 | 亚洲电影图片小说 | 亚洲高清视频在线观看 | 深夜国产在线 | 天天爱天天操天天爽 | 中文字幕亚洲在线观看 | 片网站 | 久久精品一区八戒影视 | 婷婷色伊人 | 久草国产视频 | 日韩精品欧美视频 | 亚洲精品乱码久久久久久蜜桃不爽 | 欧美性高跟鞋xxxxhd | 蜜桃av久久久亚洲精品 | 国产尤物视频在线 | 91香蕉国产在线观看软件 | 国产九九九精品视频 | 91一区啪爱嗯打偷拍欧美 | 亚洲国产精品传媒在线观看 | 五月天视频网站 | av网站在线观看播放 | 亚州激情视频 | 亚州国产精品视频 | 在线观看久久久久久 | 国产一级片直播 | 婷婷5月色 | 欧美日韩高清一区二区三区 | 黄色av电影在线观看 | 韩国av一区 | 国产精品久久网 | 色一色在线 | 日韩午夜高清 | 婷婷色中文字幕 | 高潮毛片无遮挡高清免费 | 在线视频一区观看 | 欧美性大战久久久久 | 精品国内自产拍在线观看视频 | 国产精品久久久久影视 | www色,com| 亚洲专区在线播放 | 2024国产精品视频 | 日韩国产精品久久久久久亚洲 | 欧美日韩亚洲国产一区 | 免费污片 | 激情婷婷在线 | 在线看黄色的网站 | 狠狠狠狠狠狠狠 | 亚洲午夜久久久久久久久久久 | 99精品免费在线观看 | 久久久视频在线 | 国模视频一区二区 | 亚洲精品乱码久久久一二三 | 国产高清精品在线 | 999久久a精品合区久久久 | 激情丁香综合 | 一级做a视频 | 91亚洲精品乱码久久久久久蜜桃 | 婷婷久久网 | 色老板在线 | 这里只有精品视频在线观看 | 国产精品 中文在线 | 五月综合 | 男女免费av | 亚洲视频观看 | 91丨九色丨蝌蚪丰满 | 免费手机黄色网址 | 色综合久久天天 | 亚洲精品久久久久久久不卡四虎 | 欧美日韩高清一区二区三区 | 国产视频不卡一区 | 99精品国产一区二区三区不卡 | 国产亚洲精品久久久久秋 | 麻花豆传媒一二三产区 | 午夜免费久久看 | 中文字幕在线播放视频 | 免费观看日韩 | 久久久电影 | 日本在线观看中文字幕无线观看 | 一区三区视频在线观看 | 黄色av免费在线 | 黄色小网站在线 | 99热这里只有精品1 av中文字幕日韩 | 日日夜夜精品免费观看 | 天天艹天天爽 | 99久久这里只有精品 | 成人av在线观 | 亚洲精品在线播放视频 | 91精品国产乱码在线观看 | 国产高清在线免费观看 | 国产精品乱码高清在线看 | 黄色的网站在线 | 欧美做受高潮1 | 日韩中文字幕免费在线播放 | 欧美性生活久久 | 国产又粗又猛又爽又黄的视频免费 | 国产毛片aaa| 日韩av二区| www.夜色.com | 五月天激情视频 | 亚洲四虎在线 | 探花视频在线观看 | 国产精品24小时在线观看 | 久久人91精品久久久久久不卡 | 91看片在线免费观看 | 午夜精品久久久久久99热明星 | 五月天婷婷在线观看视频 | 91久久精品一区 | av大片免费在线观看 | 国产亚洲视频系列 | 成片人卡1卡2卡3手机免费看 | 国产精品免费观看久久 | 青青河边草手机免费 | 国产成人精品亚洲a | 成人毛片在线观看视频 | 日本aa在线 | 午夜精品福利在线 | 久久精品国产成人精品 | 欧美日本啪啪无遮挡网站 | 麻豆免费精品视频 | 欧美另类tv | 奇米影视999| 国产免费美女 | 久久人人爽av | 国产精品精品久久久久久 | 免费av网站观看 | 狠狠狠狠狠狠狠狠 | 久久99视频精品 | 天天射天天艹 | 丁香激情综合久久伊人久久 | 婷婷色在线播放 | 日韩国产精品一区 | 免费在线观看午夜视频 | 久久免费视频2 | 国产精品久久久久久久久久了 | 91大神视频网站 | 久久综合五月天婷婷伊人 | 久久五月网 | japanesexxxhd奶水| 亚洲国产视频在线 | 国产123av | 欧美孕妇视频 | 青青草国产免费 | 91福利小视频 | 久影院 | 亚洲欧美国产精品va在线观看 | 91色蜜桃| 日韩专区在线播放 | 色婷婷综合久久久久中文字幕1 | 999久久久免费精品国产 | 蜜臀av夜夜澡人人爽人人 | 999久久国产精品免费观看网站 | 日本中出在线观看 | 四虎影视久久久 | 99精品在线免费观看 | 中文字幕色婷婷在线视频 | 美腿丝袜av| 国产精品色婷婷 | 国产精品第72页 | 久草视频手机在线 | 国产原创在线 | 日本公乱妇视频 | 免费视频国产 | 中国美女一级看片 | 欧美日韩国产二区 | 国产探花在线看 | 色婷婷播放 | 在线色亚洲| 精品久久一区二区三区 | 干av在线| 2018亚洲男人天堂 | 久久人人97超碰国产公开结果 | 日本中文字幕在线免费观看 | 久久五月网 | 亚洲精品欧美精品 | 成人h电影在线观看 | 国产亚洲成av人片在线观看桃 | 在线观看视频h | 91精品国产入口 | 久久99精品久久久久久三级 | av亚洲产国偷v产偷v自拍小说 | 亚洲精品日韩av | 国产小视频你懂的在线 | 精品国产免费看 | 91在线免费公开视频 | 成人免费网站在线观看 | 日韩av电影网站在线观看 | 国产亚洲欧美在线视频 | 最近免费中文字幕mv在线视频3 | 亚洲精品字幕在线 | av免费网站观看 | 亚洲日本va在线观看 | 国产黄色精品在线观看 | 久草视频在线免费播放 | 四虎4hu永久免费 | 人成在线免费视频 | 亚洲国产成人精品电影在线观看 | 欧美精品小视频 | 久久夜夜爽| 亚洲最大成人网4388xx | 久久精品香蕉 | 日韩视频1 | 免费国产ww | 国产成人a亚洲精品 | av成人在线看| 中文字幕日韩国产 | 日韩精品中文字幕久久臀 | 国产香蕉久久精品综合网 | 久久久久久国产精品免费 | 又黄又爽的免费高潮视频 | 亚洲欧美日韩在线看 | 高清在线一区 | 91片网| 久久久久免费网站 | 久久精品99北条麻妃 | 玖玖玖在线观看 | 亚洲国产97在线精品一区 | 国内免费的中文字幕 | 狠狠狠狠狠狠 | 国产黄色高清 | 国产盗摄精品一区二区 | 在线看国产日韩 | 国外调教视频网站 | 91精品国自产在线偷拍蜜桃 | 久久99精品国产99久久 | 久久国产成人午夜av影院潦草 | 69国产精品成人在线播放 | 国产亚洲aⅴaaaaaa毛片 | 久久精品成人欧美大片古装 | 午夜精品一区二区国产 | 欧美在线观看视频 | 日韩精品一区二区免费视频 | 国产传媒一区在线 | 日韩美女免费线视频 | av网在线观看 | 4hu视频| 中文字幕丝袜一区二区 | 国产精品电影在线 | 国产一级黄 | 日本久久电影网 | 狠狠色丁香婷婷综合久小说久 | www.黄色在线| 国产精品资源在线观看 | 久久网址| 国产玖玖在线 | 免费韩国av| 欧美xxxx性xxxxx高清 | 一本一道久久a久久综合蜜桃 | 国语精品视频 | 69国产在线观看 | 日韩免费专区 | 九九视频热 | 免费在线黄 | 91精品一 | 免费网站看v片在线a | 一区二区三区电影大全 | 天天草夜夜 | 国产专区一 | 狠狠干五月天 | 亚洲女人天堂成人av在线 | www.日日日.com | 色干综合 | 亚洲一区二区高潮无套美女 | 亚洲欧美国内爽妇网 | 亚洲一本视频 | 视频在线观看入口黄最新永久免费国产 | 福利视频午夜 | 99精品视频在线观看 |