redis 事務與管道

2023-05-14 18:00:28

一、事務:

1. 事務概述:

1.1 什麼是事務:

指可以一次執行多個命令,本質是一組命令的集合。
一個事務中的所有命令都會序列化,按順序的序列化執行而不會被其他命令插入,不許加塞
即:一個佇列中,一次性、順序性、排他性的執行一系列命令

1.2 與傳統關係型資料庫的事務相比redis事務的不同之處:

我覺得最關鍵的一個不同就是redis事務不能保證原子性,在MySQL的一個事務裡的命令要麼全部成功要麼全部失敗,
但是在redis事務裡,它只會把這個事務裡的一系列命令執行完,不管成功與否,事務都算結束了

2. 事務的常用操作:

2.1 事務正常執行:

輸入MULTI命令標記開啟一個事務,之後的每條命令都會進入對列,顯示QUEUED即已經進入佇列。
輸入EXEC命令,會執行事務塊內(佇列)的所有命令。

2.2 放棄事務:

在事務塊內輸入命令DISCARD,該事務塊內的所有命令不會執行,並且退出該事務塊。

2.3 事務異常(執行異常):

執行前異常一般是這種命令出錯(編譯錯誤)的異常

2.4 事務異常(執行異常):

執行後異常一般指執行錯誤的異常,這種異常,除了出錯的命令外,正常執行的命令都會在這個事務塊執行後成功執行。不能保證原子性的原因。

2.5 watch監控:

1)加監控且沒有被篡改的情況:

2)加監控出現加塞篡改的情況:

說明:

watch命令是一種樂觀鎖的實現,Redis在修改的時候會檢測資料是否被更改,如果更改了,則執行失敗
第一個視窗藍色框第5步執行結果返回為空,也就是相當於是失敗,整個事務的命令都不會成功執行,相當於DISCARD

複習:悲觀鎖和樂觀鎖

悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。
樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料。
樂觀鎖策略:提交版本必須大於記錄當前版本才能執行更新
redis是效能優先的資料庫,肯定是使用的樂觀鎖實現,因為悲觀鎖實現會頻繁加鎖,對效能的消耗大。

3)unwatch:
開啟unwatch後,在該命令之前的監控全部失效,不會對資料進行監控

4)注意:
一旦執行了EXEC,之前加的監控鎖都會被取消掉;當用戶端連線斷開時,所有監控鎖會被取消。

二、管道:

1. 管道概述:

1.1 管道出現的背景:

Redis是一種基於使用者端-伺服器端模型以及請求/響應協定的TCP服務。一個請求會遵循以下步驟:
1) 使用者端向伺服器端傳送命令分四步(傳送命令→命令排隊→命令執行→返回結果),並監聽Socket返回,通常以阻塞模式等待伺服器端響應。
2) 伺服器端處理命令,並將結果返回給使用者端。
上述兩步稱為:Round Trip Time(簡稱RTT,封包往返於兩端的時間)

如果同時需要執行大量的命令,那麼就要等待上一條命令應答後再執行,這中間不僅僅多了RTT(Round Time Trip),而且還頻繁呼叫系統IO,傳送網路請求,同時需要redis呼叫多次read()和write()系統方法,系統方法會將資料從使用者態轉移到核心態,這樣就會對程序上下文有比較大的影響了,效能不太好,o(╥﹏╥)o

1.2 管道的定義:

管道是為了解決命令往返過於頻繁而導致的RTT時長過長,僅僅是將命令打包一次性傳送,對整個redis的執行不造成其他任何影響。
它屬於批次處理命令變種優化措施,類似redis的原生批次處理命令(mset和mget),但是這種批次處理命令(例如mset)只能對string型別的資料批次處理
如果需要對多種型別資料批次處理,就必須使用管道了
所以,管道的出現能對頻繁的命令往返進行優化,從而提升redis的效能

2. 管道實操:

2.1 先清空資料庫(方便直觀地顯示操作結果):

2.2 使用管道進行批次處理:


這時候再去查詢資料庫會發現,這些命令都被成功且正確的執行了

2.3 管道與原生批命令對比:

2.4 管道與事務對比:

2.5 注意:

管道緩衝的指令只是會依次執行,不保證原子性,如果執行過程中指令發生異常,將會繼續執行後續的指令。
使用管道組裝的命令個數也不能太多,不然資料量過大,使用者端阻塞的時間可能過久,同時伺服器端此時也被迫回覆一個佇列答覆,佔用很多記憶體。