共計 3482 個字符,預計需要花費 9 分鐘才能閱讀完成。
自動寫代碼機器人,免費開通
這篇文章將為大家詳細講解有關 Redis 在項目中的應用場景是什么,丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
相信對于絕大多數程序員來說,redis 中間件應該是大家非常熟悉的。但是對于工作中經常寫業務代碼的程序員來說,他們在實際工作中可能只是用到了 set value、get value 等操作,對于 redis 缺乏整體認識。
Redis 是什么?
Redis 是一個開源的底層使用 C 語言編寫的 key-value 存儲數據庫。可用于緩存、事件發布訂閱、高速隊列等場景。而且支持豐富的數據類型:string(字符串)、hash(哈希)、list(列表)、set(無序集合)、zset(sorted set:有序集合)
Redis 在項目中的應用場景
1、緩存數據
最常用,對經常需要查詢且變動不是很頻繁的數據 常稱作熱點數據。
2、消息隊列
相當于消息訂閱系統,比如 ActiveMQ、RocketMQ。如果對數據有較高一致性要求時,還是建議使用 MQ)
3、計數器
比如統計點擊率、點贊率,redis 具有原子性,可以避免并發問題
4、電商網站信息
大型電商平臺初始化頁面數據的緩存。比如去哪兒網購買機票的時候首頁的價格和你點進去的價格會有差異。
5、熱點數據
比如新聞網站實時熱點、微博熱搜等,需要頻繁更新。總數據量比較大的時候直接從數據庫查詢會影響性能
給個愛的理由
在單節點服務器我們通常是這樣的
隨著企業的發展、業務的擴展。面對海量的數據,直接使用 MySql 會導致性能下降,數據的讀寫也會非常慢。于是我們就可以搭配緩存來處理海量數據。
于是現在我們是這樣的:
上圖只是簡述了緩存的作用,當數據繼續增大我們需要利用主從復制技術來達到讀寫分離
數據庫層直接與緩存進行交互,如果緩存中有數據直接返回客戶端,如果沒有才會從 MySql 中去查詢。從而減小了數據庫的壓力,提升了效率。
平時發布了一款新手機,會有搶購活動。同一時間段,服務端會收到很多的下單請求。
我們需要使用 redis 的原子操作來實現這個“單線程”。首先我們把庫存存在一個列表中,假設有 10 件庫存,就往列表中 push20 個數,這個數沒有實際意義,僅僅只是代表 10 件庫存。搶購開始后,每到來一個用戶,就從列表中 pop 一個數,表示用戶搶購成功。當列表為空時,表示已經被搶光了。因為列表的 pop 操作是原子的,即使有很多用戶同時到達,也是依次執行的
題外話:還有的搶購是直接在前端頁面限制請求,這些請求直接被前端攔截,并沒有到后端服務器
Redis 為什么會這么快?
1、Redis 是純內存操作,需要的時候需要我們手動持久化到硬盤中
2、Redis 是單線程,從而避開了多線程中上下文頻繁切換的操作。
3、Redis 數據結構簡單、對數據的操作也比較簡單
4、使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis 直接自己構建了 VM 機制,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求
5、使用多路 I / O 復用模型,非阻塞 I /O
多路 I / O 復用: I/O 多路復用技術是為了解決進程或線程阻塞到某個 I/O 系統調用而出現的技術,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒,就是這個文件描述符進行讀寫操作之前),能夠通知程序進行相應的讀寫操作
(學習視頻分享:redis 視頻教程)
Redis 數據類型的應用場景
前面提到了 Redis 支持五種豐富的數據類型,那么在不同場景下我們該怎么選擇呢?
String
字符串是最常用的數據類型,他能夠存儲任何類型的字符串,當然也包括二進制、JSON 化的對象、甚至是 base64 編碼之后的圖片。在 Redis 中一個字符串最大的容量為 512MB,可以說是無所不能了。
Hash
常用作存儲結構化數據、比如論壇系統中可以用來存儲用戶的 Id、昵稱、頭像、積分等信息。如果需要修改其中的信息,只需要通過 Key 取出 Value 進行反序列化修改某一項的值,再序列化存儲到 Redis 中,Hash 結構存儲,由于 Hash 結構會在單個 Hash 元素在不足一定數量時進行壓縮存儲,所以可以大量節約內存。這一點在 String 結構里是不存在的。
List
List 的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis 內部的很多實現,包括發送緩沖隊列等也都是用的這個數據結構。另外,可以利用 lrange 命令,做基于 Redis 的分頁功能,性能極佳,用戶體驗好。
Set
set 對外提供的功能與 list 類似是一個列表的功能,特殊之處在于 set 是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重復數據時,這個時候就可以選擇使用 set。
Sort Set
可以按照某個條件的權重進行排序,比如可以通過點擊數做出排行榜的數據應用。
Redis 緩存的數據一致性
真正意義上來講數據庫的數據和緩存的數據是不可能一致的,數據分為最終一直和強一致兩類。如果業務中對數據的要求必須強一直那么就不能使用緩存。緩存能做的只能保證數據的最終一致性。
我們能做的只能是盡可能的保證數據的一致性。不管是先刪庫再刪緩存 還是 先刪緩存再刪庫,都可能出現數據不一致的情況,因為讀和寫操作是并發的,我們沒辦法保證他們的先后順序。具體應對策略還是要根據業務需求來定,這里就不贅述了。
Redis 的過期和內存淘汰
Redis 存儲數據時我們可以設置他的過期時間。但是這個 key 是怎么刪除的呢?
一開始我認為是定時刪除,后來發現并不是這樣,因為如果定時刪除,需要一個定時器來不斷的負責監控這個 key,雖然內存釋放了,但是非常消耗 cpu 資源。
Redis 過期刪除采用的是定期刪除,默認是每 100ms 檢測一次,遇到過期的 key 則進行刪除,這里的檢測并不是順序檢測,而是隨機檢測。那這樣會不會有漏網之魚?顯然 Redis 也考慮到了這一點,當我們去讀 / 寫一個已經過期的 key 時,會觸發 Redis 的惰性刪除策略,直接回干掉過期的 key
內存淘汰是指用戶存儲的一部分 key 是可以被 Redis 自動的刪除,從而會出現從緩存中查不到數據的情況。加入我們的服務器內存為 2G、但是隨著業務的發展緩存的數據已經超過 2G 了。但是這并不影響我們程序的運行,因為操作系統的可見內存并不受物理內存的限制。物理內存不夠用沒關系,計算機會從硬盤中劃出一片空間來作為虛擬內存。這就是 Redis 設計兩種應用場景的初衷:緩存、持久存儲
緩存擊穿
緩存只是為了緩解數據庫壓力而添加的一層保護層,當從緩存中查詢不到我們需要的數據就要去數據庫中查詢了。如果被黑客利用,頻繁去訪問緩存中沒有的數據,那么緩存就失去了存在的意義,瞬間所有請求的壓力都落在了數據庫上,這樣會導致數據庫連接異常。
解決方案:
1、后臺設置定時任務,主動的去更新緩存數據。這種方案容易理解,但是當 key 比較分散的時候,操作起來還是比較復雜的
2、分級緩存。比如設置兩層緩存保護層,1 級緩存失效時間短,2 級緩存失效時間長。有請求過來優先從 1 級緩存中去查找,如果在 1 級緩存中沒有找到相應數據,則對該線程進行加鎖,這個線程再從數據庫中取到數據,更新至 1 級和 2 級緩存。其他線程則直接從 2 級線程中獲取
3、提供一個攔截機制,內部維護一系列合法的 key 值。當請求的 key 不合法時,直接返回。
緩存雪崩
緩存雪崩就是指緩存由于某些原因(比如 宕機、cache 服務掛了或者不響應)整體 crash 掉了,導致大量請求到達后端數據庫,從而導致數據庫崩潰,整個系統崩潰,發生災難,也就是上面提到的緩存擊穿。
如何避免雪崩:
1、給緩存加上一定區間內的隨機生效時間,不同的 key 設置不同的失效時間,避免同一時間集體失效。
2、和緩存擊穿解決方案類似,做二級緩存,原始緩存失效時從拷貝緩存中讀取數據。
3、利用加鎖或者隊列方式避免過多請求同時對服務器進行讀寫操作。
結語:
Redis 的性能極高,讀的速度是 110000 次 /s, 寫的速度是 81000 次 /s,支持事務,支持備份,豐富的數據類型。
任何事情都是兩面性,Redis 也是有缺點的:
1、由于是內存數據庫,所以單臺機器存儲的數據量是有限的,需要開發者提前預估,需要及時刪除不需要的數據。
2、當修改 Redis 的數據之后需要將持久化到硬盤的數據重新加入到內容中,時間比較久,這個時候 Redis 是無法正常運行的。
關于“Redis 在項目中的應用場景是什么”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
向 AI 問一下細節