1. 程式人生 > >Redis學習——Redis事務

Redis學習——Redis事務

Redis和傳統的關係型資料庫一樣,因為具有持久化的功能,所以也有事務的功能!
有關事務相關的概念和介紹,這裡就不做介紹。

在學習Redis的事務之前,首先丟擲一個面試的問題。

面試官:請問Redis支援事務嗎?如果支援和傳統的關係型資料的事務有什麼區別?

應試者:支援,但是是部分支援。Redis的事務和傳統的關係型資料庫事務有點不一樣,傳統的資料庫事務一組操作單元,要麼全部成功,要麼全都失敗。而Redis在執行一個命令集合的時候,可能會出現集合的一些命令成功,一些命令失敗。

Redis 事務| 菜鳥教程 :Redis 事務

Redis事務的學習筆記總結:
1:是什麼?

可以一次執行多個命令,本質是一組命令的集合。一個事務中的所有命令都會序列化,按順序地序列化執行而不會被其它命令插入,不許加塞。

2:能做什麼?

一個佇列中,一次性、順序性、排他性的執行一系列命令
1   DISCARD 
取消事務,放棄執行事務塊內的所有命令。
2   EXEC 
執行所有事務塊內的命令。
3   MULTI 
標記一個事務塊的開始。
4   UNWATCH 
取消 WATCH 命令對所有 key 的監視。
5   WATCH key [key ...] 
監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。

4:怎麼玩?

  • 案例1:正常執行
127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379> MULTI  #開始事務
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> EXEC #執行,全部執行成功
1) OK
2) OK
3) OK
127.0.0.1:6379> MGET k1 k2 k3  #檢視執行結果
1) "v1"
2) "v2" 3) "v3" 127.0.0.1:6379>
  • 案例2:放棄事務
127.0.0.1:6379> MULTI #開始事務
OK
127.0.0.1:6379> set k4 v4 
QUEUED
127.0.0.1:6379> set k5 v5 
QUEUED
127.0.0.1:6379> set k1 v11  #這裡發現出錯了,第一次設定k1 了
QUEUED
127.0.0.1:6379> DISCARD #放棄事務
OK
127.0.0.1:6379> MGET k1 k2 k3 k4 k5      #k4 k5 的值沒有設定成功
1) "v1"
2) "v2"
3) "v3"
4) (nil)
5) (nil)
127.0.0.1:6379> 
  • 案例3:全體連坐(一個出錯,全部執行失敗)
127.0.0.1:6379> KEYS *  #檢視當前的keys
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> MULTI  #開始事務
OK
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> getandset k1  #這裡有個操作出錯 ,下面報錯,
(error) ERR unknown command 'getandset'
127.0.0.1:6379> set k6 v6  # 這個命令依舊執行成功,放到Queued佇列
QUEUED
127.0.0.1:6379> EXEC  #執行,出錯
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> MGET k1 k2 k3 k4 k5 k6    #k4 k5 k6 的值都沒有設定成功,操作全部失敗
1) "v1"
2) "v2"
3) "v3"
4) (nil)
5) (nil)
6) (nil)
127.0.0.1:6379> 
  • 案例4:冤頭債主(一個出錯,出錯的不執行,其他的執行成功!)
127.0.0.1:6379> set k1 1  #將k1 修改為 1
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> MULTI  #開啟事務
OK
127.0.0.1:6379> set k4 v4 
QUEUED
127.0.0.1:6379> set v5 v5
QUEUED
127.0.0.1:6379> INCR k1  #k1 加1 
QUEUED
127.0.0.1:6379> INCR k2 #k2 加1 ,因為k2的值為v2 ,這裡最後執行會報錯
QUEUED
127.0.0.1:6379> INCR k3 #k3 加1 
QUEUED
127.0.0.1:6379> set k6 v6
QUEUED
127.0.0.1:6379> EXEC   #執行,除了 k2 k3 執行失敗,其他的都執行成功。
1) OK
2) OK
3) (integer) 2
4) (error) ERR value is not an integer or out of range    #INCR k2 執行出錯
5) (error) ERR value is not an integer or out of range      #INCR k3 執行出錯
6) OK
127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6  #看到k4 v5 k6 設定成功
1) "2"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
6) "v6"
127.0.0.1:6379> 
  • 案例5:watch監控(watch可以監控多個key,使用watch進行key的監控,相當於給key上鎖,如果在事務中,監控的key的value發生變化,則整個事務的全部命令都執行失敗)
127.0.0.1:6379> KEYS *
1) "k3"
2) "k4"
3) "k2"
4) "v5"
5) "k1"
6) "k6"
127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6
1) "2"
2) "v2"
3) "v3"
4) "v4"
5) "v5"
6) "v6"
127.0.0.1:6379> WATCH k1  #監控k1 第一步
OK
127.0.0.1:6379> MULTI  #開始事務 第二步
OK
127.0.0.1:6379> set k7 v7    #第三步
QUEUED
127.0.0.1:6379> set k2 v2222  #第四步
QUEUED
127.0.0.1:6379> set k3 v3333  #第五步
QUEUED
127.0.0.1:6379> set k8 v8  #第六步
QUEUED
127.0.0.1:6379> EXEC  #第七步  #執行結果為nil ,說明執行失敗
(nil)
127.0.0.1:6379> MGET k1 k2 k3 k4 v5 k6 k7 k8
1) "110"   #k1 的值被改了 ,其他的事務中的值都沒有成功
2) "v2"
3) "v3"
4) "v4"
5) "v5"
6) "v6"
7) (nil)
8) (nil)
127.0.0.1:6379> 
--
在執行第三 —— 第六步之間,使用另一個客戶端修改k1 的值為 成110 

另一個客服端執行:
127.0.0.1:6379> set k1 110
OK

案例5解釋:因為另一個客服端修改 了k1的值,但是k1的值是被監控的,事務在執行的時候發現k1的值被修改了,則事務中的其他操作命令也不執行,即執行失敗。

5:執行階段

  1. 開啟:以MULTI開始一個事務
  2. 入隊:將多個命令入隊到事務中,接到這些命令並不會立即執行,而是放到等待執行的事務佇列裡面
  3. 執行/撤銷:由EXEC/Discard 命令觸發/撤銷事務

6:總結

  • 單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端傳送來的命令請求所打斷
  • 沒有隔離級別的概念:佇列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務裡的更新,在事務外查詢不能看到”這個讓人萬分頭痛的問題
  • 不保證原子性:redis同一個事務中如果有一條命令執行失敗,其後的命令仍然會被執行,沒有回滾

備註知識 :

悲觀鎖:

    悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block
直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖.

樂觀鎖:

    樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,
樂觀鎖策略:提交版本必須大於記錄當前版本才能執行更新

CAS(check and set)

歡迎訪問我的csdn部落格,我們一同成長!

不管做什麼,只要堅持下去就會看到不一樣!在路上,不卑不亢!