為什麼Redis這麼快?5分鐘成為Redis高手

Linksla發表於2023-11-29

Redis簡介

Redis 是 C 語言開發的一個開源高效能鍵值對的記憶體資料庫,可以用來做資料庫、快取、訊息中介軟體等場景,是一種 NoSQL(not-only sql,非關係型資料庫)的資料庫。

Redis特點

優秀的效能,資料是儲存在記憶體中,讀寫速度非常快,可支援併發10W QPS。

  • 單執行緒單程式,是執行緒安全的,採用 IO 多路複用

  • 可作為分散式鎖

  • 支援十種資料型別

  • 支援資料持久化

可以作為訊息中介軟體使用,支援訊息釋出及訂閱。

資料型別

下表是我列舉的 常用五種資料型別的特性及其使用場景:

快取

資料快取是 Redis 最重要的一個場景,為快取而生,在 springboot 中,一般有兩種使用方式:

  • 直接透過 RedisTemplate 使用

  • 透過 Spring Cache 整合 Redis(也就是註解的方式)

使用快取遇到的問題

(1)資料一致性

在分散式環境下,快取和資料庫很容易出現資料一致性問題,如果專案對快取的要求是強一致性,那就不要使用快取。
我們只能在專案中使用策略降低快取與資料庫一致性的機率,是無法保障兩者的強一致性,一般策略包括快取更新機制,更新資料庫後及時更新快取、快取失敗時增加重試機制。

(2)快取雪崩

在瞭解雪崩潰之前,我們先了解什麼是快取雪崩現象,假設A系統每秒需要處理5000個請求,但資料庫每秒只能處理 4000 個請求,某一天,快取機器出現了當機,掛了,這時候所有的請求一下子全部落在資料庫上,資料庫肯定扛不住,報警掛掉了,這時候如果沒有采取快取設施,資料庫又急著用,重新重啟資料庫,剛重啟完成(有可能沒啟動完),請求又進來了,資料庫立馬掛掉。

這就是雪崩事件,是 Redis 快取中最致命問題之一(有一個是穿透)。大家可以看看下圖:

出現雪崩事件後不要急不要慌,我們可以在事故前中後三個方面來思考解決方案:

  • 事故前:redis 高可用方案,主從+哨兵,叢集方案,避免全盤崩潰;
  • 事故中:較少資料庫的壓力,本地 Ehcache 快取+限流及降級,避免超過資料庫承受壓力;
  • 事故後:做 Redis 持久化,一旦 Redis 重啟,可從磁碟中快速恢復資料。

我們來看看改造後的資料流程,假設使用者A傳送一個請求,系統先請求本地 Ehcache 是否有資料,如果沒有再去 Redis 請求資料,如果沒有再去資料庫請求資料,獲取到資料後同步到 Ehcache 和 redis。

限流元件的作用 :可以設定每秒請求數次,有多少透過請求,剩餘的未透過的可以走降級處理,返回一些預設的值,或者友情提示等預設操作。具體流程可以看看下圖:

這樣做的好處是:

  • 資料庫安全 在限流元件可用的情況下,資料庫不會掛掉,限流根據確保了每秒多少請求能透過;

  • 部分請求可以被處理 資料庫沒掛,就意味著至少2/5的請求可以被處理掉;
  • 高峰時期部分請求無法處理到,需要使用者多次點選,因為只有 2/5 的請求被處理,剩下的請求,使用者刷不出來介面,需要多點選幾次;
  • redis 設定的快取失效時間不是設定成同一個時間,可根據功能、業務、請求介面靈活設定快取時間: setRedis(key, value, time+Math.random()*10000);

(3)快取穿透

快取穿透是指快取和資料庫中都沒有的資料,使用者(駭客)不斷髮起請求,導致請求直接查詢資料庫,這種惡意行為攻擊場景的會直接導致資料庫掛掉,資料流程如下圖所示:

處理這種情況相對比較簡單點,這種情況是繞過redis或本地快取直接到達資料庫,可以採取以下方案:

  • 在請求介面層可以做一些校驗,比如使用者籤權、引數校驗,不合法的請求直接return;
  • 還可以針對有效id做認證或直接攔截,不符合的 id 直接過濾或採用統一key儲存到redis,下次不合法的id請求時,直接到快取中獲取資料;

  • 採用 redis 的高介面 Bloom Filter,利用高效的資料結構和演算法快速判斷出你這個 Key 是否在資料庫中存在,不存在你 return 就好了,存在你就去查 DB 重新整理 KV 再 return。

(4) 快取擊穿

上面講的穿透是針對大面積資料請求,那麼擊穿是針對一點(一個key)來來導致redis異常,但某個key是非常熱點,請求非常頻繁,處於集中式訪問現象,當這個key失效(過期)時,大量的請求就會擊穿了快取,直接請求資料庫,就像在屏障中鑿開了一個洞。

不同場景下快取擊穿解決方案

  • 資料基本不變 熱點資料value基本不更新時,可以設定成永不過期
  • 資料更新不頻繁 快取重新整理流程耗時較少時,可採用redis、zookeeper等分散式中介軟體的分散式互斥鎖或者本地互斥鎖保證少量的請求能請求到資料庫並重新更新快取,其他的流程等鎖釋放後才可以訪問新快取
  • 資料更新頻繁 採用定時執行緒,在快取過期前主動重新構建快取或延長過期時間,保證所有的請求能一直訪問快取

為什麼 Redis 這麼快

Redis 官方介紹可以達到10W+的QPS,這個資料不比 MEMCache 差,而且 Redis 是單程式單執行緒的模型,完全基於記憶體的操作,CPU 不是 Redis 的瓶頸,Redis 的瓶頸是記憶體及網路頻寬,有以下特點:

  • 使用類似於 HashMap 的原理,HashMap 的查詢及操作的時間複雜度是O(1),且絕大多數請求是純碎的記憶體操作,資料存在記憶體中;

  • 資料結構簡單,對資料操作也簡單,基於KV;

  • 不錯死鎖現象採用單執行緒操作,避免了不必要的上下文切換及競爭條件,不存在CPU切換現象,也就不存在考慮各種鎖的問題;

  • 使用非阻塞IO,多路複用IO模型。

Redis 淘汰策略

  • volatile為字首的策略都是從已過期的資料集中進行淘汰。

  • allkeys為字首的策略都是面向所有key進行淘汰。

  • LRU(least recently used)最近最少用到的。

  • LFU(Least Frequently Used)最不常用的。

  • 它們的觸發條件都是Redis使用的記憶體達到閾值時。

Redis持久化

Redis 持久化策略有兩種:

  • RDB :快照形式是直接把記憶體中的資料儲存到一個 dump 的檔案中,定時儲存,儲存策略。

  • AOF :把所有的對 Redis 的伺服器進行修改的命令都存到一個檔案裡,命令的集合。Redis 預設是快照 RDB 的持久化方式。

如果非常關心你的資料,但仍然可以承受數分鐘內的資料丟失,那麼可以額只使用 RDB 持久。

AOF 將 Redis 執行的每一條命令追加到磁碟中,處理巨大的寫入會降低Redis的效能,不知道你是否可以接受。

資料庫備份和災難恢復:定時生成 RDB 快照非常便於進行資料庫備份,並且 RDB 恢復資料集的速度也要比 AOF 恢復的速度快。

當然了,Redis 支援同時開啟 RDB 和 AOF,系統重啟後,Redis 會優先使用 AOF 來恢復資料,這樣丟失的資料會最少。

Redis主從複製

  • 從節點執行 slaveof[masterIP][masterPort],儲存主節點資訊;

  • 從節點中的定時任務發現主節點資訊,建立和主節點的 Socket 連線;

  • 從節點傳送 Ping 訊號,主節點返回 Pong,兩邊能互相通訊;

  • 連線建立後,主節點將所有資料傳送給從節點(資料同步);

  • 主節點把當前的資料同步給從節點後,便完成了複製的建立過程;

    接下來,主節點就會持續的把寫命令傳送給從節點,保證主從資料一致性。

Redis哨兵模式

我們先說說主從複製會存在問題:

  • 一旦主節點當機,從節點晉升為主節點,同時需要修改應用方的主節點地址,還需要命令所有從節點去複製新的主節點,整個過程需要人工干預。

  • 主節點的寫能力受到單機的限制。

  • 主節點的儲存能力受到單機的限制。

  • 原生複製的弊端在早期的版本中也會比較突出,比如:

    Redis 複製中斷後,從節點會發起 psync。

  • 此時如果同步不成功,則會進行全量同步,主庫執行全量備份的同時,可能會造成毫秒或秒級的卡頓。

哨兵的架構模式如下:

該系統可以執行以下四個任務:

  • 監控: 不斷檢查主伺服器和從伺服器是否正常執行。

  • 通知: 當被監控的某個 Redis 伺服器出現問題,Sentinel 透過 API 指令碼向管理員或者其他應用程式發出通知。

  • 自動故障轉移: 當主節點不能正常工作時,Sentinel 會開始一次自動的故障轉移操作,它會將與失效主節點是主從關係的其中一個從節點升級為新的主節點,並且將其他的從節點指向新的主節點,這樣人工干預就可以免了。

  • 配置提供者: 在 Redis Sentinel 模式下,客戶端應用在初始化時連線的是 Sentinel 節點集合,從中獲取主節點的資訊

來源:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70013542/viewspace-2997831/,如需轉載,請註明出處,否則將追究法律責任。

相關文章