天天看點

Redis學習4-Redis進階話題-事務8 Redis進階話題-事務

Redis學習4

  • 8 Redis進階話題-事務
    • 8.1 Redis事務
      • 8.1.1 什麼是事務
      • 8.1.2 Redis事務的操作指令
      • 8.1.3 Redis事務實作
        • 8.1.3.1 正常執行事務
        • 8.1.3.2 exec 之前放棄事務
        • 8.1.3.3 指令錯誤放棄事務
        • 8.1.3.4 主動放棄事務
      • 8.1.3 Redis的watch機制
        • 8.1.3.1 Redis的watch機制原理
        • 8.1.3.2 何時取消key的監視
        • 8.1.3.3 watch機制示範

  

8 Redis進階話題-事務

8.1 Redis事務

8.1.1 什麼是事務

  事務是指一系列操作步驟,這一系列的操作步驟,要麼完全地執行,要麼完全地不執行。 Redis 中的事務(transaction)是一組指令的集合,至少是兩個或兩個以上的指令,redis 事務保證這些指令被執行時中間不會被任何其他操作打斷

8.1.2 Redis事務的操作指令

文法: multi 
作用:标記一個事務的開始。事務内的多條指令會按照先後順序被放進一個隊列當中。
傳回值:總是傳回 ok 
           
文法:exec 
作用:執行所有事務塊内的指令 
傳回值:事務内的所有執行語句内容,事務被打斷(影響)傳回 nil 
           
文法:discard 
作用:取消事務,放棄執行事務塊内的所有指令 
傳回值:總是傳回 ok 
           
文法:watch key [key ...] 
作用:監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他指令所改動, 那麼事務将被打斷。 
傳回值:總是傳回 ok 
           
文法:unwatch 
作用:取消 WATCH 指令對所有 key 的監視。
	 如果在執行 WATCH 指令之後, EXEC 指令 或 DISCARD 指令先被執行了的話,那麼就不需要再執行 UNWATCH 了 
傳回值:總是傳回 ok 
           

8.1.3 Redis事務實作

8.1.3.1 正常執行事務

事務的執行步驟: 
首先開啟事務, 其次向事務隊列中加入指令,最後執行事務送出
 例 1:事務的執行: 
 1)multi :用 multi 指令告訴 Redis,接下來要執行的指令你先不要執行,而是把它們暫 時存起來 (開啟事務)
 2)sadd works john 第一條指令進入等待隊列(指令入隊) 
 3)sadd works rose 第二條指令進入等待隊列(指令入隊) 
 4)exce 告知 redis 執行前面發送的兩條指令(送出事務) 
           
127.0.0.1:6379> sadd works john
QUEUED
127.0.0.1:6379> sadd works rose
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> smembers works
1) "rose"
2) "john"
127.0.0.1:6379>
           

8.1.3.2 exec 之前放棄事務

事務執行 exec 之前,入隊指令錯誤(文法錯誤;嚴重錯誤導緻伺服器不能正常工作(例如記憶體不足),放棄事務

執行事務步驟:
1)MULTI 正常指令 
2)SET key value 正常指令 
3)INCR  指令文法錯誤 
4)EXEC  無法執行事務,那麼第一條正确的指令也不會執行,是以 key 的值不會設定成功 
           
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set birth 1995-11-16
QUEUED
127.0.0.1:6379> incr ab ab
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>  
           
結論:事務執行 exec 之前,入隊指令錯誤,事務終止,取消,不執行。 
           

8.1.3.3 指令錯誤放棄事務

事務執行 exec 指令後,執行隊列指令,指令執行錯誤,事務送出

執行步驟: 
 1)MULTI 正常指令 
 2)SET username zhangsan 正常指令 
 3)lpop username  正常指令,文法沒有錯誤,執行指令時才會有錯誤。  
 4)EXEC 正常執行 ,發現錯誤可以在事務送出前放棄事務,執行 discard. 
           
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set username zhangsan
QUEUED
127.0.0.1:6379> lpop username
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get username
"zhangsan"
127.0.0.1:6379>   
           

結論:在 exec執行後的所産生的錯誤, 即使事務中有某個/某些指令在執行時産生了錯誤, 事務中的其他指令仍然會繼續執行。

Redis 在事務失敗時不進行復原,而是繼續執行餘下的指令。

Redis 這種設計原則是:
Redis 指令隻會因為錯誤的文法而失敗(這些問題不能在入隊時發現),或是指令用在了錯誤類型的鍵上面,
失敗的指令并不是 Redis 導緻,而是由程式設計錯誤 造成的,這樣錯誤應該在開發的過程中被發現,
生産環境中不應出現文法的錯誤。就是在程 序的運作環境中不應該出現文法的錯誤。
而 Redis 能夠保證正确的指令一定會被執行。再者不需要對復原進行支援,是以 Redis 的内部可以保持簡單且快速
           

8.1.3.4 主動放棄事務

執行步驟: 
1) MULTI 開啟事務 
2) SET age 25  指令入隊 
3) SET age 30 指令入隊 
4) DISCARD 放棄事務,則指令隊列不會被執行 
           
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> discard
OK
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379>  
           

8.1.3 Redis的watch機制

8.1.3.1 Redis的watch機制原理

WATCH 機制原理: 
WATCH 機制:使用 WATCH 監視一個或多個 key , 跟蹤 key 的 value 修改情況, 
如果有 key 的 value 值在事務 EXEC 執行之前被修改了, 整個事務被取消。
EXEC 傳回提示資訊,表 示事務已經失敗。 
 
WATCH 機制使的事務 EXEC 變的有條件,事務隻有在被 WATCH 的 key 沒有修改的前提下 才能執行。
不滿足條件,事務被取消。使用 WATCH 監視了一個帶過期時間的鍵, 那麼即使 這個鍵過期了, 事務仍然可以正常執行 
 
大多數情況下,不同的用戶端會通路不同的鍵, 互相同時競争同一 key 的情況一般都 很少, 
樂觀鎖能夠以很好的性能解決資料沖突的問題。 
           

8.1.3.2 何時取消key的監視

1、 WATCH 指令可以被調用多次。 對鍵的監視從 WATCH 執行之後開始生效,直到調 用 EXEC 為止。
  不管事務是否成功執行, 對所有鍵的監視都會被取消。 
2、當用戶端斷開連接配接時, 該用戶端對鍵的監視也會被取消。
3、 UNWATCH 指令可以手動取消對所有鍵的監視 
           

8.1.3.3 watch機制示範

執行步驟: 首先啟動 redis-server , 在開啟兩個用戶端連接配接。 分别叫 A 用戶端 和 B 用戶端。 
           
A 用戶端 :WATCH 某個 key ,同時執行事務 
           
B 用戶端:對 A 用戶端 WATCH 的 key 修改其 value 
           
1) 在 A 用戶端設定 key : str.lp 登入人數為 10 
2) 在 A 用戶端監視 key : str.lp  
3) 在 A 用戶端開啟事務 multi 
4) 在 A 用戶端修改 str.lp 的值為 11 
5) 在 B 用戶端修改 str.lp 的值為 15 
6) 在 A 用戶端執行事務 exec 
7) 在 A 用戶端檢視 str.lp 值,A 用戶端執行的事務沒有送出,因為 WATCH 的 str.lp 的值已 經被修改了, 所有放棄事務。 
           
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set str.ip 10
OK
127.0.0.1:6379> watch str.ip
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set str.ip 11
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get str.ip
"15"
127.0.0.1:6379>  
           
127.0.0.1:6379> set str.ip 15
OK
127.0.0.1:6379>
           

繼續閱讀