事务例子_Redis事务系列之一Redis事务详解
一、前言
本章是redis事務系列知識第一章,redis事務系列主要講解以下內容:
redis 事務
redis樂觀鎖講解
redis樂觀鎖實現秒殺
我們一步一步來,本章主要講解事務。
二、事務
2.1事務闡述
講redis事務之前,我們先來看看事務的定義。
事務:一個不可分割的工作單位,事務中包括的操作要么都做,要么都不做。
但redis的事務不并不是完整意義上的事務,我們稱之為弱事務,為什么這么說呢?
redis中并沒有回滾這種機制,也就是說,在一個事務中,中間一條命令執行失敗,并不會導致前面已經執行的指令回滾。也不會造成后續的指令不做。我會在下面畫圖驗證不支持回滾。
2.2 事務命令講解
事務的命令一共就五條,為了方便大家記憶,我們先記住下面三條命令,:
1.開啟事務:MULTI
2.執行事務:EXEC
3.取消事務:DISCARD
就像mysql中用begin開啟事務、用commit結束事務一樣。redis中是用multi開啟事務,用exec執行命令。如果在exec之前你不想執行事務了,可以用discard取消當前事務。下面我們舉例說明:
開啟事務和執行事務的例子
> multi //開啟事務> set s1 aaa
> set s2 bbb
> exec //執行事務
> get s1 // 獲取s1的值
"aaa"
> get s2 // 獲取s2的值
"bbb"
開啟事務和取消事務的例子
> multi //開啟事務> set s3 222
> discard //結束事務
OK
> exec //因為事務已經在上面取消了,所以在這里執行事務會報錯。
(error) ERR EXEC without MULTI
> get s3 //事務被取消了,所以這里s3根本就沒有值
(nil)
2.3 事務為什么不支持回滾
講解“事務為什么不支持回滾”之前我們先來匯總一下redis事務執行異常的幾種情況,然后再總結事務為什么不支持回滾。
語法錯誤導致事務執行異常,該事務取消
在開啟事務后,修改h1值為11111,h2值為2222,但h2語法錯誤,最終導致事務提交失敗,h1、h2保留原值。
> set h1 11> set h2 22
> multi //開啟事務
> set h1 11111
> sets h2 2222 // 語法錯誤,下面報錯
(error) ERR unknown command `sets`, with args beginning with: `h2`, `2222`,
127.0.0.1:6379> exec //執行事務,因為前面有語法錯誤,所以此事務取消
(error) EXECABORT Transaction discarded because of previous errors.
> get h1 // h1和h2的值并沒有在事務中改變
"11"
> get h2
"22"
2.運行時錯誤(Redis類型錯誤)導致事務異常
在開啟事務后,修改s1值為1111111,s2值為2222222,但將s2的類型作為List,在運行時檢測類型錯誤,最終導致事務提交失敗,此時事務并沒有回滾,而是跳過錯誤命令繼續執行, 結果s1值改變、s2保留原值。
> set s1 11> set s2 22
> multi
> set s1 1111111
> lpush s2 2222222 //此處類型錯誤,s2的類型是字符傳,但我們把S2的類型作為List提交
> exec //提交執行事務報錯。
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
> get s1 //s1的值修改成功
"1111111"
> get s2 //s1的值修改失敗
"22"
總結:為什么Redis不支持事務回滾?
以上兩個例子總結出,多數事務失敗是由語法錯誤或者數據結構類型錯誤導致的,語法錯誤說明在命令入隊前就進行檢測的,而類型錯誤是在執行時檢測的,Redis為提升性能而采用這種簡單的事務,這是不同于關系型數據庫的,特別要注意區分。
2.4 watch和unwatch命令講解
2.4.1 watch命令
上面我們講到redis是的事務是不支持回滾的,但是我們一定要讓它回滾怎么辦呢?這就需要用的watch命令了。
watch使用要注意:watch在mutil命令之前使用.
watch的作用是:監控一個值是否發生變化,如果沒發生改變,它會執行事務隊列中的命令,提交事務;如果發生變化,將不會執行事務中的任何命令,同時事務回滾。最后無論是否回滾,Redis都會取消執行事務前的WATCH命令。
這么說不太好理解,我們畫圖表示一下:
下面我們用代碼驗證一下,場景如下:
在事務開始前用WATCH監控a1,之后修改a1為c1111,MULTI開始事務,修改a2為c2222,執行EXEC,返回nil,說明事務回滾;查看下a2的值都沒有被事務中的命令所改變。
代碼如下:
//先設置2個值,我們用監控a1,然后用a2判斷是否發生的回滾。127.0.0.1:6379> set a1 1111
127.0.0.1:6379> set a2 2222
127.0.0.1:6379> watch a1 //監聽a1
127.0.0.1:6379> set a1 c1111 // a1的值在監控后發生了改變。
127.0.0.1:6379> multi //開始事務
127.0.0.1:6379> set a2 c2222 //設置a2的值
127.0.0.1:6379> exec //執行事務,發生錯誤,事務回滾
(nil)
127.0.0.1:6379> get a2 //a2的值并沒有被更改,依舊是2222
"2222"
2.4.2 unwatch命令
unwatch命令是取消監控,這里就不過多介紹了,下面是代碼:
> set k1 1111> set k2 2222
> WATCH k1
> set k1 11 //改變k1的值
> UNWATCH //取消監控
> MULTI //開啟事務
> set k1 12
> set k2 22
> exec //執行事務成功了
1) OK
2) OK
> get k1
"12"
> get k2
"22"
三、結尾
好了,就講到這里吧,這一章雖然知識點不多,但是小編為了更加通俗地講出來也想了2、3天。
碼字不易,希望大家關注一下小編,感謝!
有什么問題或者意見,大家可以提出來。
大家幫忙關注一下我微信公眾號。關注后我有上百套學習資料和視頻課程贈送。
總結
以上是生活随笔為你收集整理的事务例子_Redis事务系列之一Redis事务详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 南海观音寺有居士证免门票吗?
- 下一篇: 95式步枪的历史和应用?