Redis之Redis的事务
1.Redis的事務是什么
Redis 事務的本質是一組命令的集合,事務支持一次執行多個命令,一個事務中所有命令都會被序列化。(redis事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令).
1.1reids事務的特點
事務同命令一樣都是Redis最小的執行單位,一個事務中的命令要么都執行,要么都不執行
在事務執行過程,會按照順序串行化執行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中
Redis的事務還能保證一個事務內的命令依次執行而不被其他命令插入
1.2.Redis的常用操作
MULTI, EXEC, DISCARD and WATCH 是Redis事務的基礎。用來顯式開啟并控制一個事務,它們允許在一個步驟中執行一組命令。并提供兩個重要的保證:
事務中的所有命令都會被序列化并按順序執行。在執行Redis事務的過程中,不會出現由另一個客戶端發出的請求。這保證 命令隊列 作為一個單獨的原子操作被執行。
隊列中的命令要么全部被處理,要么全部被忽略。EXEC命令觸發事務中所有命令的執行,因此,當客戶端在事務上下文中失去與服務器的連接.
1.2.1MULTI 命令
? 用于標記事務塊的開始。Redis會將后續的命令逐個放入隊列中,然后才能使用EXEC命令原子化地執行這個命令序列。 這個命令的運行格式如下所示:MULTI
這個命令的返回值是一個簡單的字符串,總是OK。
1.2.2. EXEC命令
? 在一個事務中執行所有先前放入隊列的命令,然后恢復正常的連接狀態。當使用WATCH命令時,只有當受監控的鍵沒有被修改時,EXEC命令才會執行事務中的命令,這種方式利用了檢查再設置(CAS)的機制()。這個命令的運行格式如下所示:EXEC
這個命令的返回值是一個數組,其中的每個元素分別是原子化事務中的每個命令的返回值。當使用WATCH命令時,如果事務執行中止,那么EXEC命令就會返回一個Null值。(如果在發送EXEC命令前客戶端斷線了,則Redis會清空事務隊列,事務中的所有命令都不會執行。而一旦客戶端發送了EXEC命令,所有的命令就都會被執行)
1.2.3. DISCARD命令
清除所有先前在一個事務中放入隊列的命令,然后恢復正常的連接狀態。如果使用了WATCH命令,那么DISCARD命令就會將當前連接監控的所有鍵取消監控。這個命令的運行格式如下所示:DISCARD
這個命令的返回值是一個簡單的字符串,總是OK。
1.2.4. WATCH命令
當某個事務需要按條件執行時,就要使用這個命令將給定的鍵設置為受監控的.
1.Watch指令,類似樂觀鎖,事務提交時,如果Key的值已被別的客戶端改變,比如某個list已被別的客戶端push/pop過了,整個事務隊列都不會被執行
2.通過WATCH命令在事務執行之前監控了多個Keys,倘若在WATCH之后有任何Key的值發生了變化,EXEC命令執行的事務都將被放棄,同時返回Nullmulti-bulk應答以通知調用者事務執行失敗。 這個命令的運行格式如下所示:WATCH key [key …]
這個命令的返回值是一個簡單的字符串,總是OK。對于每個鍵來說,時間復雜度總是O(1)。
1.2.5. UNWATCH命令
清除所有先前為一個事務監控的鍵。如果你調用了EXEC或DISCARD命令,那么就不需要手動調用UNWATCH命令。這個命令的運行格式如下所示:UNWATCH
這個命令的返回值是一個簡單的字符串,總是OK。時間復雜度總是O(1)。
2.Redis 事務的三個階段
Redis 中的事務從開始到結束也是要經歷三個階段:開啟事務,命令入列,執行事務/放棄事務
2.1開啟事務階段
? 1.multi 命令用于開啟事務
? 2.multi 命令可以讓客戶端從非事務模式狀態,變為事務模式狀態,如下圖所示
?
3.注意:multi 命令不能嵌套使用,如果已經開啟了事務的情況下,再執行 multi 命令,會提示如下錯誤:
錯誤:(error) ERR MULTI calls can not be nested執行效果,如下代碼所示:127.0.0.1:6379> multi OK 127.0.0.1:6379> multi (error) ERR MULTI calls can not be nested4.當客戶端是非事務狀態時,使用 multi 命令,客戶端會返回結果 OK ,如果客戶端已經是事務狀態,再執行 multi 命令會 報不能嵌套的錯誤,但不會終止客戶端為事務的狀態, 如下圖所示
2.2命令入列階段
1.客戶端進入事務狀態之后,將多個命令入隊到事務中,接到這些命令并不會立即執行,而是放到等待執行的事務隊列里面, 命令入列成功后會返回 QUEUED,如下代碼所示:
> multi OK > set k v QUEUED > get k QUEUED2.命令會按照先進先出(FIFO)的順序出入列,也就是說事務會按照命令的入列順序,從前往后依次執行。
執行流程如下圖所示:
2.3執行事務/放棄事務階段
? 執行事務的命令是 exec ,放棄事務的命令是 discard
?
執行事務示例代碼如下:
> multi OK > set k v2 QUEUED > exec 1) OK > get k "v2"放棄事務示例代碼如下:
> multi OK > set k v3 QUEUED > discard OK > get k "v2"3.事務錯誤&回滾
事務執行中的錯誤分為以下三類:
1.執行時才會出現的錯誤(簡稱:執行時錯誤)
2.入列時錯誤,不會終止整個事務;
3.入列時錯誤,會終止整個事務。
3.1執行時錯誤
從以下實例結果可以看出,即使事務隊列中某個命令在執行期間發生了錯誤,事務也會繼續執行,直到事務隊列中所有命令執行完成。
3.2入列時,錯誤不會導致事務結束
從以下實例結果可以看出,重復執行 multi 會導致入列錯誤,但不會終止事務,最終查詢的結果是事務執行成功了。除了重復執行 multi 命令,還有在事務狀態下執行 watch 也是同樣的效果
3.3入列錯誤會導致事務結束
3.4為什么不支持事務回滾?
不支持事務回滾的原因有以下兩個:
? 1.Redis事務的執行時,錯誤通常都是編程錯誤造成的,這種錯誤通常只會出現在開發環境中,而很少會在實際的生產環境中出現,所以他認為沒有必要為 Redis 開發事務回滾功能;
? 2.不支持事務回滾是因為這種復雜的功能和 Redis 追求的簡單高效的設計主旨不符合。
4.Redis事務的三個特性
1.單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。
2.沒有隔離級別的概念:隊列中的命令沒有提交之前都不會實際的被執行,因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務里的更新,在事務外查詢不能看到”這個
3.不保證原子性:redis同一個事務中如果有一條命令執行失敗,其后的命令仍然會被執行,沒有回滾
5.悲觀鎖與樂觀鎖
1.悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。傳統的關系型數據庫里邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖
2.樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。樂觀鎖適用于多讀的應用類型,這樣可以提高吞吐量;樂觀鎖策略:提交版本必須大于記錄當前版本才能執行更新
總結
以上是生活随笔為你收集整理的Redis之Redis的事务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: access开发精要(10)-筛选
- 下一篇: access开发精要(11)-对象命名规