?前言:此篇文章系本人學習過程中記錄下來的筆記,里面難免會有不少欠缺的地方,誠心期待大家多多給予指教。
基礎篇:
- Redis(一)
- Redis(二)
- Redis(三)
接上期內容:上期完成了Redis的持久化機制的學習。下面開始學習Redis的其他功能,話不多說,直接發車。
一、Redis事務
(一)、定義
Redis事務是一個單獨的隔離操作,它將多個命令打包成一個原子操作序列。在事務執行過程中,要么所有命令都被執行,要么都不執行。這確保了數據操作的一致性和完整性。事務中的命令會被依次放入隊列中,然后在執行階段按順序執行,不會被其它命令插入,不許加塞。
(二)、Redis事務和常規事務區別
與傳統數據庫的事務相比,Redis事務有一些獨特之處。傳統數據庫事務通常支持 ACID 特性(原子性、一致性、隔離性、持久性),而 Redis 事務不僅不保證原子性,而且在隔離性方面也有所不同。
redis特性:
1 | 單獨的隔離操作 | Redis的事務僅僅是保證事務里的操作會被連續獨占的執行,redis命令執行是單線程架構,在執行完事務內所有指令前是不可能再去同時執行其他客戶端的請求的。 |
2 | 沒有隔離級別概念 | 因為事務提交前任何指令都不會被實際執行,也就不存在”事務內的查詢要看到事務里的更新,在事務外查詢不能看到”這種問題了。 |
3 | 不保證原子性 | Redis的事務不保證原子性,也就是不保證所有指令同時成功或同時失敗,只有決定是否開始執行全部指令的能力,沒有執行到一半進行回滾的能力 |
4 | 排它性 | Redis會保證一個事務內的命令依次執行,而不會被其它命令插入。 |
(三)、實操
1、正常執行
使用MULTI開啟事務,EXEC執行事務。開啟事務之后的所有操作,都只是加入到操作隊列中,并沒有實際執行。
?
2、放棄事務
使用MULTI開啟事務,DISCARD放棄事務。
3、全部失敗
4、冤頭債主
與傳統事務數據庫區別,不一定要一起成功一起失敗,redis可以部分成功部分失敗。
INCR和INCRBY命令操作只能是整數,所以這兩條命令失敗了,其他都成功了。
5、watch監控
樂觀鎖(Optimistic Lock),顧名思義,就是很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據。樂觀鎖策略是提交版本必須?大于記錄當前版本才能執行更新。
悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數據的時候都認為別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會block直到它拿到鎖。
watch命令是一種樂觀鎖的實現,Redis在修改的時候會檢測數據是否被更改,如果更改了,則執行失敗。
5.1、正常情況
5.2、加塞情況
就是開啟對這個key監控后,另外一個redis也在操作這個key,那么這邊事務就會執行失敗。
5.3、watch小總結
在 Redis 事務中,WATCH命令用于監控一個或多個鍵,一旦被監控的鍵在事務執行之前被其他客戶端修改,那么當前事務將被取消,不會執行。
不過需要注意的是,一旦執行了EXEC命令,那么之前加的所有監控鎖都將取消,這意味著事務執行完成后,不再對監控的鍵進行監控。此外,退出Redis或者Redis宕機也會導致監控鎖取消,所以在實際應用中,需要合理把握監控鎖的生命周期,結合業務場景來確保數據操作的準確性和一致性。
(四)、事務小總結
redis的事務分為三步:
- 開啟:以MULTI開啟事務。
- 入隊:將多個命令入隊到事務中,接到這些命令并不會立即執行,而是放到等待執行的事務隊列里面。
- 執行:由EXEC命令觸發事務。
二、Redis管道
(一)、問題由來
Redis是一種基于客戶端-服務端模型以及請求/響應協議的TCP服務。一個請求會遵循以下步驟:
- 客戶端向服務端發送命令分四步(發送命令→命令排隊→命令執行→返回結果),并監聽Socker返回,通常以阻塞模式等待服務端響應。
- 服務端處理命令,并將結果返回給客戶端。
如果同時需要執行大量的命令,那么就要等待上一條命令應答后再執行,這中間不僅僅多了RTT(Round Time Trip,簡稱RTT,數據包往返于兩端的時間),而且還頻繁調用系統IO,發送網絡請求,同時需要redis調用多次read()和write()系統方法,系統方法會將數據從用戶態轉移到內核態,這樣就會對進程上下文有比較大的影響了,性能不太好。
Q&A?如何優化頻繁命令往返造成的性能瓶頸?
答:使用管道。
(二)、定義
管道(pipeline)可以一次性發送多條命令給服務端,服務端依次處理完完畢后,通過一條響應一次性將結果返回,通過減少客戶端與redis的通信次數來實現降低往返延時時間。pipeline實現的原理是隊列,先進先出特性就保證數據的順序性。
總結一句話:管道是批處理命令變種優化措施,類似Redis的原生批命令(mget和mset)。
(三)、實操
(四)、管道功能小總結
1、pipeline與原生批命令對比
- 原生批量命令是原子性(例如:mset,?mget),pipeline是非原子性。
- 原生批量命令一次只能執行一種命令,pipeline支持批量執行不同命令。
- 原生批命令是服務端實現,而pipeline需要服務端與客戶端共同完成。
2、pipeline與事務對比
- 事務具有原子性,管道不具有原子性。
- 管道一次性將多條命令發送到服務器,事務是一條一條的發,事務只有在接收到exec命令后才會執行,管道不會。
- 執行事務時會阻塞其他命令的執行,而執行管道中的命令時不會阻塞其他命令。
3、pipeline注意事項
- pipeline緩沖的指令只是會依次執行,不保證原子性,如果執行中指令發生異常,將會繼續執行后續的指令。
- 使用pipeline組裝的命令個數不能太多,不然數據量過大客戶端阻塞的時間可能過久,同時服務端此時也被迫回復一個隊列答復,占用很多內存。
三、Redis發布訂閱(了解即可)
(一)、定義
Redis發布訂閱是一種消息通信模式。客戶端可以訂閱一個或多個頻道,當有其他客戶端向這些頻道發布消息時,訂閱者會收到相應的消息。這是一種基于事件驅動的通信方式,適用于實時消息推送、實時通知等場景。
(二)、實操
開啟三個客戶端,A、B訂閱C,C發布消息,A、B能及時獲取消息。
(三)、發布訂閱功能小總結
Redis可以實現消息中間件MQ的功能,通過發布訂閱實現消息的引導和分流。但不推薦使用該功能,專業的事情交給專業的中間件處理,redis就做好分布式緩存功能。
Pub/Sub的缺點:
- 發布的消息在Redis系統中不能持久化,因此,必須先執行訂閱,再等待消息發布。如果先發布了消息,那么該消息由于沒有訂閱者,消息將被直接丟棄。
- 消息只管發送對于發布者而言消息是即發即失的,不管接收,也沒有ACK機制,無法保證消息的消費成功。
- 以上的缺點導致Redis的Pub/Sub模式就像個小玩具,在生產環境中幾乎無用武之地,為此Redis5.0版本新增了Stream數據結構,不但支持多播,還支持數據持久化,相比Pub/Sub更加的強大。但是仍然不推薦使用Stream來做MQ的功能,還是那句話,專業的事情交給專業的中間件處理。
四、總結
Redis 的事務、管道以及發布訂閱功能,賦予了開發者強大的數據處理與通信能力。事務機制保證了數據操作具備一致性和完整性,管道技術提升了客戶端與服務器之間的通信效率,發布訂閱機制則實現了實時消息推送功能。在實際項目開發過程中,可依據具體業務需求,靈活運用上述功能,充分發揮 Redis 的技術優勢,從而有效提升系統性能與用戶體驗。
ps:努力到底,讓持續學習成為貫穿一生的堅守。學習筆記持續更新中。。。。