1. 程式人生 > >Redis的事物

Redis的事物

不一致 red 指令 批量 語法錯誤 就是 介紹 操作數 inf

Redis的事物

Redis 事物常用命令

multi標記一個事物塊的開始

exec:執行所有事物塊內的命令

discard: 取消事物,放棄執行事物塊的所有命令

watch key [key ...]:

監視一個(或多個)key,如果在事物執行前這個(或這些) key 被其他命令所改動,那麽事務將被打斷。

unwatch取消watch命令對所有key的監控

Redis事物介紹

Redis 事務可以一次執行多個命令, 並且帶有以下兩個重要的保證:

1批量操作在發送 EXEC 命令前被放入隊列緩存。

收到 EXEC 命令後進入事務執行,事務中任意命令執行失敗,其余的命令依然被執行。

(並不回滾)

2在事務執行過程,其他客戶端提交的命令請求不會插入到事務執行命令序列中。

Redis的一個事務從開始到執行會經歷以下三個階段:

1開始事務。

2命令入隊。

3執行事務。

案例

(1)正常執行

開啟事物,set一些值,然後執行事物。看看能否獲取到值

技術分享圖片

(2)放棄事務

開啟事物,set一些值,但是又放棄了。最後看看值是否有修改,值並沒有被修改

技術分享圖片

(3)全體連坐

開啟一個事物,但是中間出現了語法錯誤,直接報錯了,到後面執行事物也是報錯。最後去拿值也是拿不到的。這種情況就是全體連坐。

技術分享圖片

(3)冤頭債主

開啟一個事物,做一些set操作,對一個

string類型值做遞增操作,然後結束事物。

可以看到前兩個都是成功的,只有後面是失敗的,這裏和關系性數據的事物是不一致的。

關系性數據庫:要麽一起成功,要麽一起失敗

nosql redis:將這命令當做批處理,只有當執行了exec後,才會去操作redis,一條失敗也不會影響其他的。

技術分享圖片

watch監控(重要)

悲觀鎖/樂觀鎖/CAS(Check And Set)

悲觀鎖

悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫裏邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖

這個就不解釋了,一看就懂,就是我操作數據時,那麽你們都拿不到,只能等著。

樂觀鎖

樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用於多讀的應用類型,這樣可以提高吞吐量

樂觀鎖策略:提交版本必須大於記錄當前版本才能執行更新

解釋一下:就相當於,每條數據都會有一個版本號,當我要去修改時,那麽會判斷當前版本號是否是大於數據庫中的版本號,如果是好,你就可以修改,如果不是,好,只能重新查這條數據再去做修再去提交,如果想要修改就需要這樣循環下去。

watch案例

假設:我有一張信用卡,有可用余額和欠額

可用余額:balance 初始化100

欠額:owe 初始化0

(1)無塞篡改

先監控再開啟multi,保證兩筆金額變動在同一個事務內,余額減去20,前額加20,沒有人在中間修改了那麽事物成功提交。

技術分享圖片

(1)有塞篡改

初始化余額和欠額後

先監控再開啟multi,保證兩筆金額變動在同一個事務內,余額減去20,欠額加20,中途有人修改余額,假如你老爸給你了10000的余額。

技術分享圖片

可以看到我在中間事物還沒有提交的時候,新增了10000的余額後再把事物提交,

提交事物後返回的是null,代表沒有提交成功。

總結

(1)監控了key,如果key被修改了,後面一個事務的執行失效

2一旦執行了exec之前加的監控鎖都會被取消掉了

3Watch指令,類似樂觀鎖,事務提交時,如果Key的值已被別的客戶端改變,

比如某個list已被別的客戶端push/pop過了,整個事務隊列都不會被執行

(4)通過WATCH命令在事務執行之前監控了多個Keys,倘若在WATCH之後有任何Key的值發生了變化,EXEC命令執行的事務都將被放棄,同時返回Nullmulti-bulk應答以通知調用者事務執行失敗

Redis的事物