Redis_02_redis實現事務和樂觀鎖
阿新 • • 發佈:2021-01-11
Redis 事務
1.Redis 事務可以一次執行多個命令, 並且帶有以下三個重要的保證:
- 批量操作在傳送 EXEC 命令前被放入佇列快取。
- 收到 EXEC 命令後進入事務執行,事務中任意命令執行失敗,其餘的命令依然被執行。
- 在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
一個事務從開始到執行會經歷以下三個階段:
- 開始事務。
- 命令入隊。
- 執行事務。
2.正常執行事務!
127.0.0.1:6379> multi #開啟事務
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED #進入佇列
127.0.0.1:6379(TX)> set k2 v2
QUEUED #進入佇列
127.0.0.1:6379(TX)> get k2
QUEUED #進入佇列
127.0.0.1:6379(TX)> exec #執行事務
1) OK
2) OK
3) "v2"
3.取消事務
127.0.0.1:6379> multi #開啟事務
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED #進入佇列
127.0.0.1:6379(TX)> discard #取消事務
OK
127.0.0.1:6379> get k1
(nil)
4.Redis編譯時異常 不會被執行
127.0.0.1:6379> multi #開啟事務
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED #進入佇列
127.0.0.1:6379(TX)> get k2 v2 #執行事務時報錯
(error) ERR wrong number of arguments for 'get' command
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec #執行事務
(error) EXECABORT Transaction discarded because of previous errors.
127.0 .0.1:6379> get k1 #所有的命令都不會生效
(nil)
5.Redis執行時異常 正常的命令任然會被執行
Redis單條命令式保證原子性,但是事務不保證原子性!
127.0.0.1:6379> multi #開啟事務
OK
127.0.0.1:6379(TX)> set k1 "v1"
QUEUED #進入佇列
127.0.0.1:6379(TX)> incr k1 #字串自增會報錯 但是其他命令任然會執行
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> get k2
"v2"
Redis實現鎖
1.悲觀鎖:
-
每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會阻塞直到它拿到鎖
2.樂觀鎖 :
-
每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號機制和CAS演算法實現。
-
實現: 獲取version,更新的時候比較version
3.Redis正常轉賬
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money #監視money 物件
OK
127.0.0.1:6379> multi #開啟事務
OK
127.0.0.1:6379(TX)> decrby money 20
QUEUED
127.0.0.1:6379(TX)> incrby out 20
QUEUED
127.0.0.1:6379(TX)> exec #提交事務
1) (integer) 80
2) (integer) 20
4.多執行緒轉賬失敗(實現回滾)
執行緒1正常轉賬
執行緒2 線上程1提交之前修改了money
#執行緒2
127.0.0.1:6379> get money
"100"
127.0.0.1:6379> incrby money 100
(integer) 200
127.0.0.1:6379> get money
"200"
#執行緒1
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money #監視money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 10
QUEUED
127.0.0.1:6379(TX)> incrby out 10
QUEUED
127.0.0.1:6379(TX)> exec #事務失敗
(nil)
127.0.0.1:6379> get money
"200"
##########################################################################
#在事務提交失敗的時候需要先解除監視,然後再次監視
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> watch
(error) ERR wrong number of arguments for 'watch' command
127.0.0.1:6379> watch money
OK