學了這麼久的Redis,竟然還不知道事務

Redis支持事務嗎,有說支持的,有說半支持的,我這裏進行一波演示,看看到底支持不支持。在演示事務之前,首先要了解一下這幾個命令。
multi開啓事務
exec執行事務
discard取消事務
watch key [key ...]監視事務
unwatch取消監視事務
下面通過一個轉賬的例子進行演示事務。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> get money
QUEUED
127.0.0.1:6379> exec
1) OK
2) "100"

這是一個正常的事務問題,就是開啓了一個事務,事務裏有一組數據,然後執行,這裏的每一條指令都是放到一個隊列裏的,當執行的時候,會逐條執行。
下面演示一個取消事務的

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> get money
QUEUED
127.0.0.1:6379> discard
OK

這個也是正常的取消了
如果在我們執行事務的時候,出現了語法錯誤,那麼整個事務都不會被執行了

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> sett age 20
(error) ERR unknown command `sett`, with args beginning with: `age`, `20`, 
127.0.0.1:6379> get money
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

可以看出,當出現語法錯誤的時候,整個事務都不會被執行,還有一種錯誤,不是語法錯誤,而是運行時錯誤。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name "hzy"
QUEUED
127.0.0.1:6379> incr name
QUEUED
127.0.0.1:6379> get name
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) "hzy"

我們讓一個字符串自增,出現了錯誤,但是事務的其他語句還是正常執行了(這應該就是別人說的Redis是半支持事務吧)。
還有一種情況就是,當我們執行事務的時候,還未執行exec,然後有其他客戶端來干擾了。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> incr money
QUEUED
127.0.0.1:6379> exec
1) OK
2) (integer) 101

如果在執行exec之前,另一個客戶端執行了如下操作

127.0.0.1:6379> set money 500
OK

然後客戶端1再執行exec,我們get一下

127.0.0.1:6379> get money
"101"

可以看出,這是事務執行完的結果,而那個500就沒有成功,爲了解決這一問題,出現了鎖,用watch監視,也就是我們的樂觀鎖。

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set money 100
QUEUED
127.0.0.1:6379> incr money
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get money
"500"

這裏我們對money進行了監視,在執行exec之前我們在客戶端2執行如下

127.0.0.1:6379> set money 500
OK

然後再執行exec,由於對money進行了watch監視,所以就返回了nil。當我們再get money的時候,此時就是剛剛設置的500了,而事務相當於沒有執行。
這裏需要注意,當我們執行了exec、discard或unwatch的時候,都會自動的取消監視。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章