Redis的事務(wù)、樂(lè)觀鎖和悲觀鎖

Redis的事務(wù)、樂(lè)觀鎖和悲觀鎖

一、是什么

可以一次執(zhí)行多個(gè)命令,本質(zhì)是一組命令的集合。
一個(gè)事務(wù)中的所有命令都會(huì)序列化,按照順序地串行化執(zhí)行而不會(huì)被其他命令插入,不許加塞

二、能干嘛

一個(gè)隊(duì)列中,一次性、順序性、排他性的執(zhí)行一系列命令

三、怎么玩

Redis中開(kāi)啟事務(wù)的命令是:MULTI ,這個(gè)命令通常會(huì)回復(fù)一個(gè)OK【回復(fù)的是OK,但是這個(gè)事能不能辦,什么時(shí)候辦,辦不辦的成不知道】,用戶將會(huì)一次性的打多個(gè)命令,而代替執(zhí)行,按順序執(zhí)行,Redis將這些命令入隊(duì),所有的命令將會(huì)通過(guò)命令:EXEC 來(lái)被調(diào)用執(zhí)行。

如果用命令:DISCARD 表示放棄丟棄,言下之意是放棄本次的批處理操作

常用命令:

DISCARD:取消事務(wù),放棄執(zhí)行事務(wù)塊內(nèi)的所有命令

EXEC:執(zhí)行所有事務(wù)塊內(nèi)的命令

MULTI:標(biāo)記一個(gè)事務(wù)塊的開(kāi)始

UNWATCH:取消 WATCH 命令對(duì)所有 key 的監(jiān)控

WATCH  key [key . . . ]:件事一個(gè)(或多個(gè))key,如果在事務(wù)執(zhí)行之前這個(gè)(或這些)key被其他命令所改動(dòng),那么事務(wù)將被打斷

正常執(zhí)行:


image.png

放棄事務(wù):


image.png

全體連坐:【在事務(wù)塊中只要有一條命令執(zhí)行是錯(cuò)的,那么整個(gè)事務(wù)塊就不會(huì)執(zhí)行】
image.png

冤頭債主:【如果在事務(wù)塊中所有命令都正確,但是結(jié)果會(huì)產(chǎn)生錯(cuò)誤,那么冤有頭債有主,誰(shuí)錯(cuò)找誰(shuí)】


image.png

watch監(jiān)控:
悲觀鎖

悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,當(dāng)其他線程想要訪問(wèn)數(shù)據(jù)時(shí),都需要阻塞掛起。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制,比如行鎖、表鎖,讀鎖,寫(xiě)鎖等,都是在操作之前先上鎖。

在Java中,synchronized的思想也是悲觀鎖。

樂(lè)觀鎖:【沖突檢測(cè)和數(shù)據(jù)更新】

樂(lè)觀鎖(Optimistic Lock),顧名思義,就是很樂(lè)觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候回判斷一下再次期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)等機(jī)制。樂(lè)觀鎖適用于多讀的應(yīng)用類(lèi)型,這樣可以提高吞吐量。

樂(lè)觀鎖策略:提交版本必須大于記錄當(dāng)前版本才能執(zhí)行更新

一般會(huì)使用版本號(hào)機(jī)制或CAS操作實(shí)現(xiàn):

version方式:一般是在數(shù)據(jù)表中加上一個(gè)數(shù)據(jù)版本號(hào)version字段,表示數(shù)據(jù)被修改的次數(shù),當(dāng)數(shù)據(jù)被修改時(shí),version值會(huì)加一。當(dāng)線程A要更新數(shù)據(jù)值時(shí),在讀取數(shù)據(jù)的同時(shí)也會(huì)讀取version值,在提交更新時(shí),若剛才讀取到的version值為當(dāng)前數(shù)據(jù)庫(kù)中的version值相等時(shí)才更新,否則重試更新操作,直到更新成功。

核心SQL代碼:

update table set x=x+1, version=version+1 where id=#{id} and version=#{version};

CAS(Check And Set【先檢查再動(dòng)手設(shè)置】)

CAS操作方式:即 compare and set,CAS是樂(lè)觀鎖技術(shù),涉及到三個(gè)操作數(shù),數(shù)據(jù)所在的內(nèi)存值,預(yù)期值,新值。當(dāng)需要更新時(shí),判斷當(dāng)前內(nèi)存值與之前取到的值是否相等,若相等,則用新值更新,若失敗則重試,一般情況下是一個(gè)自旋操作,即不斷的重試。


無(wú)加塞篡改,先監(jiān)控再開(kāi)啟 MULTI ,保證兩筆金額變動(dòng)在同一個(gè)事務(wù)內(nèi)


如下圖:就模擬了一個(gè)購(gòu)物的過(guò)程,在買(mǎi)的過(guò)程中,別人會(huì)給你打錢(qián),當(dāng)你要完成支付的時(shí)候報(bào)錯(cuò)了


image.png

解決:【使用 UNWATCH 取消對(duì)當(dāng)前 key 的監(jiān)控,之后再一次進(jìn)行監(jiān)控(得到最新的數(shù)據(jù)),直到成功為止】


image.png

注意:


一旦執(zhí)行了 EXEC,之前加的監(jiān)控所都會(huì)被取消掉*


四、小結(jié)

通過(guò) WATCH 命令在事務(wù)執(zhí)行之前監(jiān)控了多個(gè) Keys,倘若在 WATCH 之后有任何 Key 的值發(fā)生變化,EXEC 命令執(zhí)行的事務(wù)都將被放棄,同時(shí)返回 Nullmulti-bulk 應(yīng)答以通知調(diào)用者事務(wù)執(zhí)行失敗

五、三階段

開(kāi)啟:以 MULTI 開(kāi)始一個(gè)事務(wù)

入隊(duì):將多個(gè)命令入隊(duì)到事務(wù)中,接到這些命令并不會(huì)立即執(zhí)行,而是放到等待執(zhí)行的事務(wù)隊(duì)列里面

執(zhí)行:由 EXEC 命令觸發(fā)事務(wù)

六、三特性

單獨(dú)的隔離操作:事務(wù)中所有的命令多會(huì)序列化、按順序地執(zhí)行。事務(wù)在執(zhí)行的過(guò)程中,不會(huì)被其他客戶端發(fā)送來(lái)的命令請(qǐng)求所打斷

沒(méi)有隔離級(jí)別的概念:隊(duì)列中的命令沒(méi)有提交之前都不會(huì)實(shí)際的被執(zhí)行,因?yàn)槭聞?wù)提交前任何指令都不會(huì)被實(shí)際的執(zhí)行,也就是不存在 “ 事務(wù)內(nèi)的查詢要看到事務(wù)里面的更新,在事務(wù)外查詢不能看到 ” 這個(gè)是讓人萬(wàn)分頭痛的問(wèn)題

不保證原子性:Redis 同一個(gè)事務(wù)中如果有一條命令執(zhí)行失敗,其后的命令仍然會(huì)被執(zhí)行,沒(méi)有回滾
————————————————
版權(quán)聲明:本文為CSDN博主「少年唐玄奘」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_40585396/article/details/93489689

?著作權(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)容