Redis 实用技术——事务
引言
redis的事務不像關系型數據庫的事務那樣完整。
“快”是redis的特征,在事務管理的過程中,使用muti命令開啟事務塊,當輸入多條命令后,再使用exec命令執行事務塊中的全部命令。
Redis事務可以保證兩件事:
1、隔離性:事務是一個單獨的隔離操作,這和關系型數據庫的事務原則是一致的,事務中的所有命令都會順序執行,且中途不會被其他事務打斷。
2、原子性:要么全部執行,要么全不執行。
一、查看幫助
MULTI、EXEC、DISCARD、WATCH 是 Redis 事務的相關命令:
MULTI 命令用于開啟一個事務,它總是返回OK,執行后,客戶端可以繼續向服務器發送多條命令,這些命令會被暫時存放到隊列中而不執行。
EXEC 命令負責觸發并執行事務中的所有命令,如果客戶端在使用 MULTI 開啟一個事務之后,因為掉線沒有成功執行 EXEC ,那么事務中的所有命令都不會被執行。
DISCARD 客戶端可以通過這個命令清空事務隊列,視為放棄執行事務。
二、并發下的事務
由于Redis是單線程處理全部用戶請求,因此,在并發事務中,每個命令都會排隊執行,事務之間很可能出現“先刪后取”的問題。
不論 multi 執行的先后,Redis 只根據最先接收到的?exec 命令來執行事務。
如上圖所示,綠色事務先開啟事務塊,但是在執行 exec 提交事務之前,被一個刪除事務提前執行,那么綠色事務就無法正確獲取 key 的value。
三、WATCH 提供的 CAS
WATCH 可以讓 exec 命令有條件的執行:事務只能在所有被監視的key都沒有被修改的前提下執行。這是watch為redis提供的check-and-set(CAS)行為。
watch 命令可以被調用多次,對 key 的監視從 watch 執行之后生效,直到調用 exec 為止。當exec 被調用時,不管事務是否成功執行,對所有 key 的監視都會被取消。
使用 無參的 unwatch ,可以手動取消對所有 key 的監視。
如果有至少一個被監視的 key 在 exec 執行之前被修改,那么整個事務都會被取消,exec 返回 nil-reply 來表示事務已經失敗。
上面的兩個客戶端,左側先watch stu 監視,右側客戶端更改 stu ,左側再開啟事務并修改 stu,最后 exec ,返回結果為 nil,且stu最終并沒有被改變。
這種形式的鎖被稱為樂觀鎖,它是一種非常強大的鎖機制,并且因為大多數情況下,不同的客戶端會訪問不同的鍵,碰撞的情況一般都很少,所以通常并不需要進行重試。
另外,當客戶端斷開連接時,該客戶端對 key 的監視也會被取消。
四、事務中的錯誤
使用事務時可能會遇到兩種錯誤:
1、執行 exec 之前入列命令錯誤,如語法、參數名、參數數量等。或其他嚴重錯誤,內存不足等。
2、執行 exec 之后失敗,例如,事務中的命令與處理的類型不匹配等等。
對于第一種錯誤,在 Redis 2.6.5 之前,客戶端會檢查命令入列的返回值,如果是 QUEUED,入列成功,否則入列失敗。
從 2.6.5 開始,服務器會對命令入列失敗的情況進行記錄,并在客戶端調用 exec 命令時,拒絕并自動放棄這個事務。
這種改進方式,是為了在 Redis 管道中包含事務,如果是以前的做法,那么一條拼接的多條命令如果中間某個出了問題將很難快速有效的執行,而改進后,情況就變得簡單,發送事務和讀取事務的回復都只需要和服務器進行一次通訊。
對于第二種錯誤,exec 執行時或之后出錯,并沒有什么特別的處理,即使事務中有某些命令在執行時產生錯誤,事務中的其他命令仍然會繼續執行。
至于事務回復中,有一些是 OK 而有一些是 ERR,就需要由客戶端自己決定如何處理,Redis 不會停止執行事務中的命令。
這就是 “Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令”的含義。這樣做有以下幾點優點:
1、Redis 命令只會因為錯誤的語法而失敗(并且這些問題不能在入隊時發現),或是命令用在了錯誤類型的鍵上面:這也就是說,從實用性的角度來說,失敗的命令是由編程錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生產環境中。
2、因為不需要對回滾進行支持,所以 Redis 的內部可以保持簡單且快速。
所以,通常對于精度要求不是特別嚴格的場合,就可以使用 redis 事務,而不應該將其用在類似銀行轉賬的嚴格的事務場合。
?
?
?
總結
以上是生活随笔為你收集整理的Redis 实用技术——事务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring读取properties配置
- 下一篇: mysql 读取properties_J