大家好,我是漫步coding, 最近在整理2022年Redis最新面試題, 大家也可以通過我下面的博客地址在線閱讀, 今天講講第3篇 - Redis事務。本文首發于公眾號:漫步coding
2022年Redis最新面試題目錄
Redis數據結構
Redis事務
Redis數據持久化
Redis集群
Redis淘汰策略
Redis分布式鎖
Redis緩存問題
運維和部署
事務
怎么理解 Redis 事務?
Redis事務執行過程
Redis事務的一些使用場景
Redis事務與Redis pipeline的區別
集群模式下Redis事務如何保證原子性
怎么理解 Redis 事務?
出現概率: ★★★★
Redis事務的本質是一組命令的集合。事務支持一次執行多個命令,一個事務中所有命令都會被序列化。在事務執行過程,會按照順序串行的執行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中。
總結說:Redis事務就是一次性、順序性、排他性的執行一個隊列中的一系列命令。
1)、Redis事務相關命令和使用
MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事務相關的命令。
MULTI: 開啟事務,redis會將后續的命令逐個放入隊列中,然后使用EXEC命令來原子化執行這個命令系列。
EXEC: 執行事務中的所有操作命令。
DISCARD: 取消事務,放棄執行事務塊中的所有命令。
WATCH: 監視一個或多個key,如果事務在執行前,這個key(或多個key)被其他命令修改,則事務被中斷,不會執行事務中的任何命令。
UNWATCH: 取消WATCH對所有key的監視。
example:
127.0.0.1:6379>MULTI
OK
127.0.0.1:6379>SET?name'漫步coding'
QUEUED
127.0.0.1:6379>SET?brief'一個專注于算法、數據庫、職場的公眾號'
QUEUED
127.0.0.1:6379>GET?name
QUEUED
127.0.0.1:6379>EXEC
1)?OK
2)?OK
3)"漫步coding"
畫重點,?Redis事務不支持Rollback
事實上Redis命令在事務執行時可能會失敗,但仍會繼續執行剩余命令而不是Rollback(事務回滾)。如果你使用過關系數據庫,這種情況可能會讓你感到很奇怪。然而針對這種情況Redis官方也給出了解釋:
Redis命令可能會執行失敗,僅僅是由于錯誤的語法被調用(命令排隊時檢測不出來的錯誤),或者使用錯誤的數據類型操作某個Key:? ?這意味著,實際上失敗的命令都是編程錯誤造成的,都是開發中能夠被檢測出來的,生產環境中不應該存在。(這番話,徹底甩鍋,“都是你們自己編程錯誤,與我們無關”。)
由于不必支持Rollback,Redis內部簡潔并且更加高效。
Redis事務執行過程
出現概率: ★★★
一個Redis事務從開始到執行會經歷以下三個階段:
1)開始事務。
2)命令放入Queue。
3)執行事務。
1)開始事務
MULTI命令的執行標記著事務的開始:
127.0.0.1:6379>MULTI
OK
這個命令唯一做的就是, 將客戶端的 REDIS_MULTI 選項打開, 讓客戶端從非事務狀態切換到事務狀態。
2)命令放入Queue
當客戶端處于非事務狀態下時, 所有發送給服務器端的命令都會立即被服務器執行:
127.0.0.1:6379>SET?name'漫步coding'
OK
127.0.0.1:6379>GET?name
"漫步coding"
但是, 當客戶端進入事務狀態之后, 服務器在收到來自客戶端的命令時, 不會立即執行命令, 而是將這些命令全部放進一個事務隊列里, 然后返回QUEUED, 表示命令已入隊:
127.0.0.1:6379>MULTI
OK
127.0.0.1:6379>SETname"漫步coding"
QUEUED
127.0.0.1:6379>GETname
QUEUED
3)執行事務
當客戶端進入事務狀態之后, 客戶端發送的命令就會被放進事務隊列里。
EXEC 、 DISCARD 、 MULTI 和 WATCH 這四個命令 —— 當這四個命令從客戶端發送到服務器時, 它們會像客戶端處于非事務狀態一樣, 會被服務器立即執行。
127.0.0.1:6379>EXEC
1)OK
2)OK
3)?"漫步coding"
4)、關于WATCH命令
WATCH指令,有點類似樂觀鎖,事務提交時,如果 key 的值已被別的客戶端改變,比如某個 list 已被別的客戶端push/pop 過了,整個事務隊列都不會被執行。(當然也可以用 Redis 實現分布式鎖來保證安全性,屬于悲觀鎖)
WATCH機制的作用是,在事務執行前,監控一個或多個鍵的值變化情況,當事務調用EXEC命令執行時,WATCH機制會先檢查監控的鍵是否被其它客戶端修改了。如果修改了,就放棄事務執行,避免事務的隔離性被破壞。然后,客戶端可以再次執行事務,此時,如果沒有并發修改事務數據的操作了,事務就能正常執行,隔離性也得到了保證。
WATCH機制的具體實現是由WATCH命令實現的,我給你舉個例子,你可以看下面的圖,進一步理解下WATCH命令的使用。
example:
127.0.0.1:6379>setk1
OK
127.0.0.1:6379>WATCHk
OK
127.0.0.1:6379>setk2
OK
127.0.0.1:6379>MULTI
OK
127.0.0.1:6379>setk3
QUEUED
127.0.0.1:6379>EXEC
(nil)
127.0.0.1:6379>getk
"2"
提交事務,但k值不會被修改為3,因為在事務開啟之前k的值被修改了。
Redis事務的一些使用場景
出現概率: ★★★
可利用watch命令監聽key,實現樂觀鎖,來保證不會出現沖突,應用場景比如秒殺來防止超賣。
秒殺場景偽代碼如下:
這塊代碼其實還沒有想好, 如果有經驗的朋友,歡迎留言, 后續我研究透徹會也專門寫一篇秒殺場景的文章。
settotal_quantity100
WATCH?goods_quantity
MULTI
ifgoods_quantity?<?total_quantity?&&?user_idnotin'user_list'
incr?goods_quantity
set'user_list'user_id
end
EXEC
Redis事務與Redis pipeline的區別
出現概率: ★★★
Redis Pipeline主要用于批量發送命令,一次性發送多個請求,一次性讀取所有返回結果??梢怨澥∵B接->發送命令->返回結果這個過程所產生的時間(RTT),減少read()和write()的系統調用(從用戶態到內核態之間的切換)次數。
Redis事務、Redis Pipeline表面上它們可以作為批量執行命令的方式,但實際也有許多區別。
1)、命令緩沖隊列方式不同
Redis事務包含的命令是緩沖在服務端內存隊列,而Redis Pipeline則是緩沖在客戶端本地內存中;
2)、請求次數不同
Redis事務中每個命令都需要發送到服務端,而Pipeline只需要發送一次,請求次數更少;
3)、原子性保證
Redis事務可以保證命令原子化執行,而Pipeline不保證原子性。
Redis事務、Pipeline都只能作用于單個節點。集群環境下,執行Redis命令時,會根據key計算出一個槽位(slot),然后根據槽位重定向到特定的節點上執行操作。
4)、在使用事務時,建議配合 Pipeline 使用。
a) 如果不使用 Pipeline,客戶端是先發一個 MULTI 命令到服務端,客戶端收到 OK,然后客戶端再發送一個個操作命令,客戶端依次收到 QUEUED,最后客戶端發送 EXEC 執行整個事務(文章例子就是這樣演示的),這樣消息每次都是一來一回,效率比較低,而且在這多次操作之間,別的客戶端可能就把原本準備修改的值給修改了,所以無法保證隔離性。
b) 而使用 Pipeline 是一次性把所有命令打包好全部發送到服務端,服務端全部處理完成后返回。這么做好的好處,一是減少了來回網絡 IO 次數,提高操作性能。二是一次性發送所有命令到服務端,服務端在處理過程中,是不會被別的請求打斷的(Redis單線程特性,此時別的請求進不來),這本身就保證了隔離性。我們平時使用的 Redis SDK 在使用開啟事務時,一般都會默認開啟 Pipeline 的,可以留意觀察一下。
集群模式下Redis事務如何保證原子性
出現概率: ★★★
Redis事務中每個命令都需要發送到服務端, 不過Redis事務可以保證命令原子化執行
Redis事務只能作用于單個節點。集群環境下,執行Redis命令時,會根據key計算出一個槽位(slot),然后根據槽位重定向到特定的節點上執行操作。
也歡迎關注我的公眾號:?漫步coding。一起交流, 在coding的世界里漫步, ?? ?回復:?redis, 免費獲取最新Redis面試題(含答案)。