事務本質:一組命令的集合!一個事務中的所有命名都會被序列化,在事務執行過程中,會按照順序執行!
一次性、順序性、排他性!執行一系列命令!
Redis事務沒有隔離級別的概念
所有的命令在事務中,並沒有執行!只有發起執行命令的時候才會執行!Exec
Redis單條命令是保證原子性的(要麼同時成功,要麼同時失敗),但是事務不保證原子性!
redis的事務:
- 開啟事務(MULTI)
- 命名入隊(。。。)
- 執行事務()
正常執行事務!
127.0.0.1:6379[1]> MULTI # 開啟事務
OK
127.0.0.1:6379[1]> set k1 v1 # 命令入隊
QUEUED
127.0.0.1:6379[1]> set k2 v2
QUEUED
127.0.0.1:6379[1]> get k2
QUEUED
127.0.0.1:6379[1]> set k3 v3
QUEUED
127.0.0.1:6379[1]> EXEC # 執行事務
1) OK
2) OK
3) "v2"
4) OK
放棄事務
127.0.0.1:6379[1]> multi # 開啟事務
OK
127.0.0.1:6379[1]> set k1 v1
QUEUED
127.0.0.1:6379[1]> set k2 v2
QUEUED
127.0.0.1:6379[1]> set k4 v2
QUEUED
127.0.0.1:6379[1]> DISCARD # 取消事務
OK
127.0.0.1:6379[1]> get k4 # 事務佇列中命令都不會被執行
(nil)
編譯型異常(程式碼有問題!命令有錯!),事務中所有的命令都不會被執行
127.0.0.1:6379[1]> MULTI
OK
127.0.0.1:6379[1]> set k1 v1
QUEUED
127.0.0.1:6379[1]> set k2 v2
QUEUED
127.0.0.1:6379[1]> set k3 v3
QUEUED
127.0.0.1:6379[1]> getset k3 # 錯誤的命名
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379[1]> set k4 v4
QUEUED
127.0.0.1:6379[1]> set k5 v5
QUEUED
127.0.0.1:6379[1]> EXEC # 執行事務報錯!
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379[1]> get k5 # 所有的命令都不會被執行!
(nil)
執行時異常(1/0),如果事務佇列中存在語法性,那麼執行命令的時候,其它命名可以正常執行的,錯誤命令丟擲異常
127.0.0.1:6379[1]> set k1 v1
OK
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> incr k1
QUEUED
127.0.0.1:6379[1]> set k2 v2
QUEUED
127.0.0.1:6379[1]> set k3 v3
QUEUED
127.0.0.1:6379[1]> get k3
QUEUED
127.0.0.1:6379[1]> exec
1) (error) ERR value is not an integer or out of range # 雖然一條命令報錯了,但是依舊正常執行成功了
2) OK
3) OK
4) "v3"
127.0.0.1:6379[1]> get k2
"v2"
127.0.0.1:6379[1]> get k3
"v3"
監控!Watch
悲觀鎖:
- 很悲觀,什麼時候都會出問題,無論做什麼都會加鎖!
樂觀鎖: - 很樂觀,認為什麼時候都不會出問題,所以不會上鎖!更新資料的時候去判斷一下,在此期間是否有人修改這個資料
- 獲取version
- 更新的時候比較 version
Redis 監視測試
正常執行成功
127.0.0.1:6379[1]> set money 100
OK
127.0.0.1:6379[1]> set out 0
OK
127.0.0.1:6379[1]> watch money # 監視 mony
OK
127.0.0.1:6379[1]> multi # 事務正常結束,資料期間沒有發生變動,這個時候就正常執行成功
OK
127.0.0.1:6379[1]> decrby money 20
QUEUED
127.0.0.1:6379[1]> incrby out 20
QUEUED
127.0.0.1:6379[1]> exec
1) (integer) 80
2) (integer) 20
測試多執行緒修改值,使用watch可以當作redis的樂觀鎖操作
127.0.0.1:6379[1]> watch money # 監視money
OK
127.0.0.1:6379[1]> multi
OK
127.0.0.1:6379[1]> decrby money 10
QUEUED
127.0.0.1:6379[1]> incrby money 10
QUEUED
127.0.0.1:6379[1]> get money
QUEUED
127.0.0.1:6379[1]> exec # 執行之前,另一個執行緒修改了值,就會導致事務執行失敗
(nil)
使用exec和discard會自動解鎖類似於JUC程式設計中的自旋鎖。
如果修改失敗,獲取最新的值就好了。
本作品採用《CC 協議》,轉載必須註明作者和本文連結