leveldb 併發寫入處理

2022-04-01 21:19:54 字數 1683 閱讀 3839

在併發寫入的時候,leveldb巧妙地利用乙個時間視窗做batch寫入,這部分**值得一讀:

status dbimpl::write(const writeoptions& options, writebatch* my_batch) 

if (w.done)

// b end

// may temporarily unlock and wait.

status status = makeroomforwrite(my_batch == null);

uint64_t last_sequence = versions_->lastsequence();

writer* last_writer = &w;

if (status.ok() && my_batch != null)

}if (status.ok())

mutex_.lock();

if (sync_error)

}if (updates == tmp_batch_) tmp_batch_->clear();

versions_->setlastsequence(last_sequence);

} while (true)

if (ready == last_writer) break;

} // notify new head of write queue

if (!writers_.empty())

return status;

}

假設同時有w1, w2, w3, w4, w5, w6 併發請求寫入。

b部分**讓競爭到mutex資源的w1獲取了鎖。w1將它要寫的資料新增到了writers_佇列裡去,此時佇列只有乙個w1, 從而其順利的進行buildbatchgroup。當執行到34行時mutex_互斥鎖釋放,之所以這兒可以釋放mutex_,是因為其它的寫操作都不滿足隊首條件,進而不會進入log和memtable寫入階段。這時(w2, w3, w4, w5, w6)會競爭鎖,由於b段**中不滿足隊首條件,均等待並釋放鎖了。從而佇列可能會如(w3, w5, w2, w4).

繼而w1進行log寫入和memtable寫入。 當w1完成log和memtable寫入後,進入46行**,則mutex_又鎖住,這時b段**中佇列因為獲取不到鎖則佇列不會修改。

隨後59行開始,w1被pop出來,由於ready==w, 並且ready==last_writer,所以直接到71行**,喚醒了此時處於隊首的w3.

w3喚醒時,發現自己是隊首,可以順利的進行進入buildbatchgroup,在該函式中,遍歷了目前所有的佇列元素,形成乙個update的batch,即將w3, w5, w2, w4合併為乙個batch. 並將last_writer置為此時處於隊尾的最後乙個元素w4,34行**執行後,因為釋放了鎖資源,佇列可能隨著dbimpl::write的呼叫而更改,如佇列狀況可能為(w3, w5, w2, w4, w6, w9, w8).

35-45行的**將w3, w5, w2, w4整個的batch寫入log和memtable. 到65行,分別對w5, w2, w4進行了一次cond signal.當判斷到完w4 == lastwriter時,則退出迴圈。72行則對隊首的w6喚醒,從而按上述步驟依次進行下去。

這樣就形成了多個併發write 合併為乙個batch寫入log和memtable的機制。

golang 併發demo 寫入 redis

源 package main import fmt runtime strconv time gopkg.in redis.v3 var jobnum runtime.numcpu 每次寫入redis的數量 除以 jobnum 為了保證改變了任務數,總量不變,便於測試 procnum 100000 ...

Hibernate 處理併發

一 事務 指運算元據庫的乙個程式執行單無,這些操作要麼全部成功,要麼全部失敗以保證資料的完成性和統一性.二 多事務併發引起的問題 a 第一類丟失更新 撤銷乙個事務時把其它事務更新的資料也覆蓋了。for example 事務a 和b 同時訪問數 據data 如果事務b 更新了資料,但事務a執行了回滾操...

核心併發處理

隨著硬體的發展,smp 對稱多處理器 已經很普遍,如果核心的排程機制是可搶占的,那麼smp和核心搶占是多執行緒執行的兩種場景。當多個執行緒同時訪問核心的資料結構時,我們就需要對其做序列化處理。自旋鎖和互斥體 訪問共享資源的 區稱為臨界區。自旋鎖 spinlock 和互斥體 mutex,mutual ...