NoSQL之Redis高級實用命令詳解--事務處理

Redis事務處理

Redis對事務的支持目前還比較簡單。Redis只能保證一個client發起的事務中的命令可以連續執行,而中間不會插入其他client的命令。當一個client在一個連接中發出multi命令時,這個連接會進入一個事務上下文,該連接後續的命令不會立即執行,而是先放到一個隊列中,當執行exec命令時,redis會順序的執行隊列中的所有命令。

1.multi:開啓一個事務 exec執行一個事務

我們來看下面的例子:

127.0.0.1:6379> set money 100
OK

127.0.0.1:6379> get money
"100"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby money 150
QUEUED
127.0.0.1:6379> incrby money 150
QUEUED
127.0.0.1:6379> decrby money 100
QUEUED
127.0.0.1:6379> exec
1) (integer) 250
2) (integer) 400
3) (integer) 300
127.0.0.1:6379> get money
"300"

首先我設置money爲100,然後用multi開啓事務之後的操作就會被queued(放入隊列存儲),直到執行exec命令之後,隊列中的命令一起被執行,money被兩次+150然後-100最後結果是300.

注意:如果在multi和exec之間執行了一條錯誤命令,那麼exec執行也不會成功。

127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.

2.discard:取消一個事務

127.0.0.1:6379> get money
"300"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set money 200
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI
127.0.0.1:6379> get money
"300"

發現事務被取消之後再執行exec,就會告訴你沒有事務了。

money還是原來的300沒變。

3.redis事務的缺點

127.0.0.1:6379> set name 'test'
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr money
QUEUED
127.0.0.1:6379> incr name
QUEUED
127.0.0.1:6379> exec
1) (integer) 301
2) (error) ERR value is not an integer or out of range

發現事務並沒有回滾,而是把正確的執行了,而錯誤的沒有執行。

這個和第一種說的還不一樣,第一步中說的如果你在multi和exec中間執行了一條錯誤的命令(語法錯誤),那麼整個事務會失敗。而如果你沒有語法錯誤,那麼就不會回滾,也就失去了事務的真正意義,這是redis對事務處理有待改進的地方。

4.樂觀鎖複雜事務控制

樂觀鎖:大多數是基於數據版本(version)的記錄機制實現的。即爲數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是通過爲數據表添加一個“version”字段來實現取出數據時,將此版本號一同讀出,之後更新時,對此版本號+1.此時,將提交數據的版本號與數據表對應記錄的當前版本號進行對比,如果提交的數據版本號大於數據庫當前版本號,則予以更新,否則認爲是過期數據。-------svn 的版本控制就是最好的例子

Redis的樂觀鎖實例:假設有一個money的key,我們開2個session來對money進行賦值操作,我們來看一下結果如何?

Session1:

127.0.0.1:6379> get money
"301"
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby money 49
QUEUED

Session2:

127.0.0.1:6379> set money 400
OK
127.0.0.1:6379> get money
"400"

Session1:

127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get money
"400"

首先我們在session1中開啓了對money的監控(watch key開啓對key鍵的監控),然後開啓一個事務,把命令incrby money 49放到事務隊列中,等待exec執行處理。

之後我們開啓session2,在session2中我們直接set money 400,這個時候我們在session2中get一下money發現已經變成400

之後我們回到session1中再用exec去執行事務隊列中得incrby money 49這條命令,發現結果是nil也就是沒有成功,用get命令看一下money發現是400,而不是449.

整個過程就實現了一個樂觀鎖。

對watch的特別說明:

watch命令會監聽給定的key,當exec的時候如果監視的key從調用watch後發生過變化,則整個事務會失敗。也可以調用watch多次監聽多個key,這樣就可以對指定的key加樂觀鎖了。注意watch的key是對整個連接有效的,事務也一樣。如果連接斷開,監視和事務都會被自動清除。當然了exec,discard,unwatch命令都會清除連接中的所有監視。

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