一、概述
Redis中的Multi和Pipleline都可以一次性執行多個命令,但是Pipeline只是把多個redis指令一起發出去,redis並沒有保證這些指令執行的順序,且減少了多次網絡傳遞的開銷,因而其執行效率很高;Multi相當於一個redis的transaction,保證整個操作的有序性,通過watch這些key,可以避免這些key在事務的執行過程中被其它的命令修改,從而導致得的到結果不是所期望的。
官方介紹MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事務相關的命令,事務可以一次執行多個命令,但是必須滿足2個條件:
- 事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。
- 事務是一個原子操作:事務中的命令要麼全部被執行,要麼全部都不執行。執行和是否成功是2個概念,並不是一個失敗報錯等,其他就失敗。redis對事務是部分支持。如果最開始語法等就有提交錯誤,就相當於java的編譯器都過不了,那麼肯定全部不執行。如果在執行過程中報錯,已經全部執行了,但是誰報錯找誰,其他正常執行放行。各取所需!這裏的事務並不是要麼全部成功,要麼全部失敗,全部執行和全部成功(或者都失敗)是2個概念。
二、命令介紹
- MULTI:開啓事務,總是返回OK
- EXEC:提交事務
- DISCARD:放棄事務(放棄提交執行)
- WATCH:監控
- QUEUED:將命令加入執行的隊列
三、示例演示
1、開啓事務
可以看到即使開了事務,事務中正確的命令也得到了執行,不正確的命令沒有被執行,誰出錯誰負責。
2、對部分命令增加watch
增加watch命令,可以確保被watch的key在事務的執行期間,如果被其它連接修改了,則當前事務則會在執行exec時報錯,事務被中斷,事務中所有的命令都不會執行。
1)對名爲t1的key增加watch
127.0.0.1:6379> watch t1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set t1 t111
QUEUED
127.0.0.1:6379> set t2 v222
QUEUED
127.0.0.1:6379> set t3 v333
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get t1
"v111"
127.0.0.1:6379> get t2
"v2"
127.0.0.1:6379> get t3
"t33"
此時在事務的執行區間,即在執行了multi之後未執行exec之前,其它連接執行了修改t1的如下操作:
127.0.0.1:6379> set t1 v111
OK
在執行exec命令時就報了(nil)這樣一個錯誤結果,表示當前事務執行失敗。通過後續的get命令查看t1、t2和t3的值,只有t1的值發生了變化,是被其它連接修改了,當前事務中的命令都沒有被執行。
2)對名爲t2的key增加watch
127.0.0.1:6379> watch t2
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set t1 t111
QUEUED
127.0.0.1:6379> set t2 v222
QUEUED
127.0.0.1:6379> set t3 v333
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get t1
"v111"
127.0.0.1:6379> get t2
"v222"
127.0.0.1:6379> get t3
"t33"
127.0.0.1:6379> unwatch
OK
在事務區間,其它連接對t2進行了修改:
127.0.0.1:6379> set t2 v222
OK
當執行事務提交命令exec時,發現被watch的t2被修改了,當前事務執行失敗,通過get命令查看,只有t2的值發生了變化,是被其它連接修改了的,當前事務全部命令都沒有執行。
這兩個增加對key進行watch的示例,演示了被watch的key可以是事務中的任意key,只要是被watch的key被修改,整個事務都不會執行。