pika中鎖的應(yīng)用

pika作為類redis的存儲(chǔ)系統(tǒng),為了彌補(bǔ)在性能上的不足,在整個(gè)系統(tǒng)中大量使用多線程的結(jié)構(gòu),涉及到多線程編程,勢(shì)必需要為線程加鎖來(lái)保證數(shù)據(jù)訪問(wèn)的一致性和有效性。其中主要用到了四種鎖

  1. 互斥鎖
  2. 讀寫鎖
  3. 行鎖

互斥鎖和挑揀鎖比較常見(jiàn),不過(guò)多描述,這里主要說(shuō)一下另外兩種鎖的應(yīng)用。

讀寫鎖

應(yīng)用場(chǎng)景

應(yīng)用掛起指令,在掛起指令的執(zhí)行中,會(huì)添加寫鎖,以確保,此時(shí)沒(méi)有其他指令執(zhí)行。其中掛起指令有:

  1. trysync
  2. bgsave
  3. flushall
  4. readonly

作用和意義

保證當(dāng)前服務(wù)器在執(zhí)行掛起指令時(shí),只有一個(gè)線程處在running狀態(tài),而其他指令,則可以并發(fā)同時(shí)在不同線程中執(zhí)行。

行鎖

行鎖,用于對(duì)一個(gè)key加鎖,保證同一時(shí)間只有一個(gè)線程對(duì)一個(gè)key進(jìn)行操作。

作用和意義:

pika中存取的數(shù)據(jù)都是類key,value數(shù)據(jù),不同key所對(duì)應(yīng)的數(shù)據(jù)完全獨(dú)立,所以只需要對(duì)key加鎖可以保證數(shù)據(jù)在并發(fā)訪問(wèn)時(shí)的一致性,行鎖相對(duì)來(lái)說(shuō),鎖定粒度小,也可以保證數(shù)據(jù)訪問(wèn)的高效性。

應(yīng)用場(chǎng)景

在pika系統(tǒng)中,對(duì)于數(shù)據(jù)庫(kù)的操作都需要添加行鎖,主要在應(yīng)用于兩個(gè)地方,在系統(tǒng)上層指令過(guò)程中和在數(shù)據(jù)引擎層面。在數(shù)據(jù)引擎層面添加行鎖就可以保證對(duì)于數(shù)據(jù)庫(kù)訪問(wèn)的一致性和正確性。在pika系統(tǒng)中,指令執(zhí)行的地方有兩處:

  1. worker 用于執(zhí)行從客戶端接收到的指令
  2. bgworker 用于執(zhí)行從master同步過(guò)來(lái)
    的指令

在worker和bgworker需要添加行鎖的地方,都是針對(duì)于寫指令(會(huì)改變數(shù)據(jù)狀態(tài),如SET,HSET)。pika的主動(dòng)同步是依靠binlog來(lái)完成,而binlog中則記錄改變數(shù)據(jù)狀態(tài)的指令,來(lái)保證master和slave的數(shù)據(jù)庫(kù)狀態(tài)一致。一條寫指令的執(zhí)行,主要有兩個(gè)部分:

  1. 更改數(shù)據(jù)庫(kù)狀態(tài)

  2. 將指令添加到binlog中

為了保證寫指令可以正確添加到binlog中,需要對(duì)整個(gè)指令的執(zhí)行過(guò)程加鎖。如下圖

如果執(zhí)行的是讀指令,數(shù)據(jù)庫(kù)狀態(tài)不會(huì)改變,那么則不需要在pika層面對(duì)key添加行鎖,只需要在nemo層面添加行鎖就可以保證數(shù)據(jù)訪問(wèn)的正確性。

具體實(shí)現(xiàn)

在pika系統(tǒng)中,一把行鎖就可以維護(hù)所有key。在行鎖的實(shí)現(xiàn)上是將一個(gè)key與一把互斥鎖相綁定,并將其放入哈希表中維護(hù),來(lái)保證每次訪問(wèn)key的線程只有一個(gè),但是不可能也不需要為每一個(gè)key保留一把互斥鎖,只需要當(dāng)有多條線程訪問(wèn)同一個(gè)key時(shí)才需要鎖,在所有線程都訪問(wèn)結(jié)束之后,就可以銷毀這個(gè)綁定key的互斥鎖,釋放資源。

為實(shí)現(xiàn)每個(gè)key的鎖按需存在,在這里實(shí)現(xiàn)了RefMutex,對(duì)普通Mutex進(jìn)行了一層封裝,其中維護(hù)了訪問(wèn)所綁定key的線程個(gè)數(shù)ref。當(dāng)一個(gè)線程訪問(wèn)key時(shí),先在行鎖維護(hù)的哈希表中查找,如果已經(jīng)有了,則直接ref+1,并加鎖;如果沒(méi)有則創(chuàng)建RefMutex,放入哈希表中。當(dāng)一個(gè)線程訪問(wèn)結(jié)束,則ref減1,如果ref為0,則銷毀這把互斥鎖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容