四 redis學習筆記之事務

來源:互聯網
上載者:User
  redis對事務的支援目前還比較簡單。redis只能保證一個client發起的事務中的命令可以連續的執行,而中間不會插入其他client的命令。 由於redis是單線程來處理所有client的請求的所以做到這點是很容易的。一般情況下redis在接受到一個client發來的命令後會立即處理並 返回處理結果,但是當一個client在一個串連中發出multi命令有,這個串連會進入一個事務上下文,該串連後續的命令並不是立即執行,而是先放到一 個隊列中。當從此串連受到exec命令後,redis會順序的執行隊列中的所有命令。並將所有命令的運行結果打包到一起返回給client.然後此串連就 結束事務上下文。下面可以看一個例子
redis> multi
OK
redis> incr a
QUEUED
redis> incr b
QUEUED
redis> exec
1. (integer) 1
2. (integer) 1

從這個例子我們可以看到incr a ,incr b命令發出後並沒執行而是被放到了隊列中。調用exec後倆個命令被連續的執行,最後返回的是兩條命令執行後的結果
我們可以調用discard命令來取消一個事務。接著上面例子
redis> multi
OK
redis> incr a
QUEUED
redis> incr b
QUEUED
redis> discard
OK
redis> get a
"1"
redis> get b
"1"

可以發現這次incr a incr b都沒被執行。discard命令其實就是清空事務的命令隊列並退出事務上下文。

  雖說redis事務在本質上也相當於序列化隔離等級的了。但是由於事務內容相關的命令只排隊並不立即執行,所以事務中的寫操作不能依賴事務中的讀操作結果。看下面例子

redis> multi
OK
redis> get a
QUEUED
redis> get b
QUEUED
redis> exec
1. "1"
2. "1"

發現問題了吧。假如我們想用事務實現incr操作怎麼辦?可以這樣做嗎?
redis> get a
"1"
redis> multi
OK
redis> set a 2
QUEUED
redis> exec
1. OK
redis> get a,
"2"

結 論很明顯這樣是不行的。這樣和 get a 然後直接set a是沒區別的。很明顯由於get a 和set a並不能保證兩個命令是連續執行的(get操作不在事務上下文中)。很可能有兩個client同時做這個操作。結果我們期望是加兩次a從原來的1變成3. 但是很有可能兩個client的get a,取到都是1,造成最終加兩次結果卻是2。主要問題我們沒有對共用資源a的訪問進行任何的同步
也就是說redis沒提供任何的加鎖機制來同步對a的訪問。

還好redis 2.1後添加了watch命令,可以用來實現樂觀鎖。看個正確實現incr命令的例子,只是在前面加了watch a
redis> watch a
OK
redis> get a
"1"
redis> multi
OK
redis> set a 2
QUEUED
redis> exec
1. OK
redis> get a,
"2"

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

redis的事務實現是如此簡單,當然會存在一些問題。第一個問題是redis只能保證事務的每個命令連續執行,但是如果事務中的一個命令失敗了,並不復原其他命令,比如使用的命令類型不符。

redis> set a 5
OK
redis> lpush b 5
(integer) 1
redis> set c 5
OK
redis> multi
OK
redis> incr a
QUEUED
redis> incr b
QUEUED
redis> incr c
QUEUED
redis> exec
1. (integer) 6
2. (error) ERR Operation against a key holding the wrong kind of value
3. (integer) 6

可以看到雖然incr b失敗了,但是其他兩個命令還是執行了。

最 後一個十分罕見的問題是 當事務的執行過程中,如果redis意外的掛了。很遺憾只有部分命令執行了,後面的也就被丟棄了。當然如果我們使用的append-only file方式持久化,redis會用單個write操作寫入整個事務內容。即是是這種方式還是有可能只部分寫入了事務到磁碟。發生部分寫入事務的情況 下,redis重啟時會檢測到這種情況,然後失敗退出。可以使用redis-check-aof工具進行修複,修複會刪除部分寫入的事務內容。修複完後就 能夠重新啟動了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.