Redis 事務

HuDu發表於2020-09-18
事務本質:一組命令的集合!一個事務中的所有命名都會被序列化,在事務執行過程中,會按照順序執行!
一次性、順序性、排他性!執行一系列命令!

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 協議》,轉載必須註明作者和本文連結

相關文章