1. 程式人生 > 實用技巧 >Redis_02_redis實現事務和樂觀鎖

Redis_02_redis實現事務和樂觀鎖

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