一個Redis事務,可以讓你征服面試官半小時。

2020-10-15 11:00:57

理解原子性

我們知道,java中的 i++ 或者 ++i 這些自增操作不具備原子性,因為自增操作在我們程式碼層面是一個指令,但是在 jvm 底層,它分為這兩個步驟:

  1. 從區域性變數表中讀取 i 的值壓入運算元棧
  2. 將區域性變數表中 i 的值加1

若 jvm 在執行第 1 步的時候,其他執行緒先於這個執行緒改變了 i 的值,然後執行第二步後得出的值就不是我們希望的。

在 redis 中也有類似的自增操作,如我們之前學的 string 資料型別中的 incr 指令,它可以對一個 integer 型別的值加1。但是 incr 指令與 java 自增不一樣的是,它是一個原子操作,因為 incr 是呼叫作業系統底層的指令,它不會被其他執行緒打斷。所以 incr 指令具有原子性。

為什麼叫原子性?

原子性其實就是有類似原子的性質,我們知道原子中有質子和中子,他們構成了原子,不可分割,如果分割了,就不是一個原子了,是不是很好理解。整理redis的同時也整理了最近兩個月最新的面試題。需要的朋友可以點選:這個,點這個!!,備註:csdn。
在這裡插入圖片描述

什麼是事務

事務就是指一系列操作,這些操作要麼同時成功,要麼同時失敗,它是一種原子操作。原子就是一個整體,不可分割,事務中的這些操作也是一樣。
假設有這樣一個場景:張三向李四轉賬 100 塊錢,最少需要經歷兩個步驟

  1. 張三的銀行卡中錢減100塊
  2. 李四的銀行卡中錢加100塊

在沒有事務的情況下,可能會導致 1 號操作執行成功,2 號操作執行失敗,那結果是張三的錢少了 100 塊,李四的錢卻沒增加,張三的 100 塊憑空消失了,這肯定會出問題,所以這兩部操作必須要放在事務中執行,要麼轉賬成功,要麼轉賬失敗,這就是事務的作用。

redis事務

redis 是單執行緒的程式,每個指令都保證原子性,但是不保證多個指令的原子性。
當有多個使用者端連線同一個 redis 時,使用者端之間會競爭cpu資源,來爭奪 rdis 指令的執行權,所以如果一個 client 要執行一系列指令時,可能會被其他使用者端打斷。

要使多個指令也具有原子性,可以使用 redis 事務
redis 事務保證兩點:

  1. 執行一個事務時,所有的命令都會被順序執行,且不會被其他使用者端打斷
  2. 執行一個事務時,所有命令要麼同時成功,要麼同時失敗

如果 redis 開啟 AOF 模式,在執行 redis 事務之前,redis 會先把事務寫在磁碟中再執行命令。如果事務執行到一半,redis 程序突然就掛了,那麼就會導致事務中只有一部分指令執行成功,還有一部分指令還未執行。這種情況下,在 redis 下一次啟動時會檢測到錯誤,並退出 redis。使用 redis-check-aof 工具可以對 AOF 檔案進行修復,刪除掉磁碟中的未執行成功的事務,然後重新啟動載入 AOF 檔案,redis 就恢復到事務沒有執行建立的狀態,就可以正常啟動了

事務相關的命令

和 redis 事務有關的指令有:

  • multi
  • exec
  • discard

下面開始介紹每個命令

multi

使用 multi 指令來開啟事務

127.0.0.1:6379> set zhangsan 1000
OK

127.0.0.1:6379> set lisi 1000
OK

127.0.0.1:6379> multi
OK

127.0.0.1:6379> incrby zhangsan -100
QUEUED

127.0.0.1:6379> incrby lisi 100
QUEUED

multi 指令返回 ok,證明事務開啟成功。
開啟事務後,接下來執行每條正確的指令都返回 QUEUE,代表命令被放入等待佇列,但並沒有執行。

exec

使用 exec 命令來執行事務

127.0.0.1:6379> set zhangsan 1000
OK

127.0.0.1:6379> set lisi 1000
OK

127.0.0.1:6379> multi
OK

127.0.0.1:6379> incrby zhangsan -100
QUEUED

127.0.0.1:6379> incrby lisi 100
QUEUED

127.0.0.1:6379> exec   # 執行事務
1) (integer) 900
2) (integer) 1100

使用 exec 執行事務後,會按順序返回事務中每天指令的返回結果。
還整理了Java核心的知識點,大家也可以看看。需要的朋友可以點選:這個,點這個!!,備註:csdn。
在這裡插入圖片描述

discard

如果事務建立成功,但你又不想執行了,使用 discard 命令來取消

127.0.0.1:6379> multi                  # 開啟事務
OK

127.0.0.1:6379> incrby zhangsan -100
QUEUED

127.0.0.1:6379> incrby lisi 100
QUEUED

127.0.0.1:6379> discard                 # 取消事務
OK

redis 事務樂觀鎖

樂觀鎖,即認為所有時候都不會出現問題,它不會去加鎖,他會在修改資料的時候判斷這個資料是否被改動過,如果沒有被其他人改動過,就更新資料。

在 redis 中也有樂觀鎖的操作,來防止資料出現問題,現在有如下一個場景:

你想通過事務對 redis 中的 key/value 進行修改,在沒有執行 exec 命令之前,這時候另一個 client 修改了這個 key/value,這樣再執行 exec 後可能會出現問題。這種情況下用 redis 的樂觀鎖操作就可以很輕鬆解決
在 redis 中有一種 check and set(CAS)的樂觀鎖操作,相關命令如下

  • watch
  • unwatch

watch

通過 watch 命令來監視這個 key/value,如果發現該 key/value 被修改,則呼叫 exec 時事務不會被執行

127.0.0.1:6379> watch zhangsan lisi   # 監視 zhangsan 和 lisi
OK

127.0.0.1:6379> multi
OK

127.0.0.1:6379> incrby zhangsan -100
QUEUED

127.0.0.1:6379> incrby lisi 100
QUEUED

================ 這時候zhangsan的值被其他使用者端修改=======================

127.0.0.1:6379> exec   # 事務執行失敗
(nil)

unwatch

取消監視,與 watch 命令相對
在執行 exec 後,不管是否執行成功,watch 命令都會 unwatched
使用者端退出後,watch 命令也會 unwatched

127.0.0.1:6379> watch zhangsan lisi   # 監視 zhangsan 和 lisi
OK

127.0.0.1:6379> multi
OK

127.0.0.1:6379> incrby zhangsan -100
QUEUED

127.0.0.1:6379> incrby lisi 100
QUEUED

127.0.0.1:6379> unwatch  # 取消監視
OK

和事務相關的錯誤

在 redis 事務中,可能會發生兩種錯誤

1、編譯型錯誤

在 multi 後,exec 呼叫之前,由於輸入不正確的 redis 命令導致的錯誤

127.0.0.1:6379> multi
OK

127.0.0.1:6379> sets zhangsan 22   # 事務中命令輸錯
(error) ERR unknown command `sets`, with args beginning with: `zhangsan`, `22`, 

127.0.0.1:6379> set zhangsan 22
QUEUED

127.0.0.1:6379> exec   # 事務執行不成功
(error) EXECABORT Transaction discarded because of previous errors.

在這種情況下事務不會執行成功

2、執行時錯誤

在 exec 呼叫之後,由於 redis 命令執行不成功導致的錯誤

127.0.0.1:6379> set test abc
OK

127.0.0.1:6379> multi
OK

127.0.0.1:6379> incr test   # 由於test中存的不是 integer,在exec時會出錯
QUEUED

127.0.0.1:6379> set info aaa
QUEUED

127.0.0.1:6379> exec
1) (error) ERR value is not an integer or out of range
2) OK

從執行結果看出,在 exec 時,即使其中有命令出錯,後面的命令不會被影響,依舊會被執行從這裡也可以看出,redis 不支援回滾

最後提供免費的Java架構學習資料,學習技術內容包含有:Spring,Dubbo,MyBatis, RPC, 原始碼分析,高並行、高效能、分散式,效能優化,微服務 高階架構開發等等。

點選:點這個!點這個!暗號:csdn。

還有Java核心知識點+全套架構師學習資料和視訊+一線大廠面試寶典+面試簡歷模板可以領取+阿里美團網易騰訊小米愛奇藝快手嗶哩嗶哩面試題+Spring原始碼合集+Java架構實戰電子書。
在這裡插入圖片描述