713
技術社區[雲棲]
Redis開發運維實踐專題功能之事務
3.2 事務
用Multi(Start Transaction)、Exec(Commit)、Discard(Rollback)實現。 在事務提交前,不會執行任何指令,隻會把它們存到一個隊列裏,不影響其他客戶端的操作。在事務提交時,批量執行所有指令。 一般情況下redis在接受到一個client發來的命令後會立即處理並返回處理結果,但是當一個client在一個連接中發出multi命令後,這個連接會進入一個事務上下文,該連接後續的命令並不是立即執行,而是先放到一個隊列中。當從此連接受到exec命令後,redis會順序的執行隊列中的所有命令。並將所有命令的運行結果打包到一起返回給client.然後此連接就結束事務上下文。
Redis還提供了一個Watch功能,你可以對一個key進行Watch,然後再執行Transactions,在這過程中,如果這個Watched的值進行了修改,那麼這個Transactions會發現並拒絕執行。
使用discard命令來取消一個事務。
注意:redis隻能保證事務的每個命令連續執行(因為是單線程架構,在執行完事務內所有指令前是不可能再去同時執行其他客戶端的請求的,也因此就不存在"事務內的查詢要看到事務裏的更新,在事務外查詢不能看到"這個讓人萬分頭痛的問題),但是如果事務中的一個命令失敗了,並不回滾其他命令。另外,一個十分罕見的問題是當事務的執行過程中,如果redis意外的掛了。隻有部分命令執行了,後麵的也就被丟棄了。注意,如果是筆誤,語法出現錯誤,則整個事務都無法執行。
一個簡單案例表明出錯也不會回滾:
127.0.0.1:6379> del q1
(integer) 0
127.0.0.1:6379> exists q1
(integer) 0
127.0.0.1:6379> multi
OK
127.0.0.1:6379> rpush q1 bar
QUEUED
127.0.0.1:6379> scard q1
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> exists q1
(integer) 1
當然如果我們使用的append-only file方式持久化,redis會用單個write操作寫入整個事務內容。即是是這種方式還是有可能隻部分寫入了事務到磁盤。發生部分寫入事務的情況下,redis重啟時會檢測到這種情況,然後失敗退出。可以使用redis-check-aof工具進行修複,修複會刪除部分寫入的事務內容。修複完後就能夠重新啟動了。
Redis開發運維實踐指南
本文為《Redis開發運維實踐指南》內容,該書作者為黃鵬程,已授權雲棲社區轉載。
最後更新:2017-05-08 10:01:37