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