Redis進階知識一覽

小懶程式設計日記發表於2022-05-17

Redis的持久化機制

RDB: Redis DataBase

  1. 什麼是RDB
    RDB∶每隔一段時間,把記憶體中的資料寫入磁碟的臨時檔案,作為快照,恢復的時候把快照檔案讀進記憶體。如果當機重啟,那麼記憶體裡的資料肯定會沒有的,那麼再次啟動redis後,則會恢復。

  2. 備份與恢復
    記憶體備份-->磁碟臨時檔案
    臨時檔案-->恢復到記憶體

  3. RDB優劣勢

    • 優勢
      1. 每隔一段時間備份,全量備份
      2. 災備簡單,可以遠端傳輸
      3. 子程式備份的時候,主程式不會有任何io操作(不會有寫入修改或刪除),保證備份資料的的完整性
      4. 相對AOF來說,當有更大檔案的時候可以快速重啟恢復
    • 劣勢
      1. 發生故障時,有可能會丟失最後一次的備份資料
      2. 子程式所佔用的記憶體比會和父程式一模一樣,這會造成CPU負擔
      3. 由於定時全量備份是重量級操作,所以對於實時備份,就無法處理了。
  4. RDB的配置

    1. 儲存位置,可以在redis.conf自定義∶/user/local/redis/working/dump.rdb
    2. 儲存機制∶
save 900 1       # 如果1個快取更新,則15分鐘後備份
save 300 10      # 如果10個快取更新,則5分鐘後備份
save 60 10000    # 如果10000個快取更新,則1分鐘後備份
  1. stop-writes-on-bgsave-error
    • yes∶如果save過程出錯,則停止寫操作
    • no∶ 可能造成資料不一致
  2. rdbcompression
    • yes∶開啟rdb壓縮模式
    • no∶關閉,會節約cpu損耗,但是檔案會大,道理同nginx
  3. rdbchecksum
    • yes∶使用CRC64演算法校驗對rdb進行資料校驗,有10%效能損耗
    • no∶不校驗

總結
RDB適合大量資料的恢復,但是資料的完整性和一致性可能會不足

AOF: Append Only File

  RDB會丟失最後一次備份的rdb檔案,但是其實也無所謂,其實也可以忽略不計,畢竟是快取,丟了就丟了,但是如果追求資料的完整性,那就的考慮使用AOF了。
AOF特點

  1. 以日誌的形式來記錄使用者請求的寫操作。讀操作不會記錄,因為寫操作才會存儲存。
  2. 檔案以追加的形式而不是修改的形式。
  3. redis的aof恢復其實就是把追加的檔案從開始到結尾讀取執行寫操作。

優勢

  1. AOF更加耐用,可以以秒級別為單位備份,如果發生問題,也只會丟失最後一秒的資料,大大增加了可靠性和資料完整性。所以AOF可以每秒備份一次,使用fsync操作。
  2. 以log日誌形式追加,如果磁碟滿了,會執行redis-check-aof 工具
  3. 當資料太大的時候,redis可以在後臺自動重寫aof。當redis繼續把日誌追加到老的檔案中去時,重寫也是非常安全的,不會影響客戶端的讀寫操作。
  4. AO日誌包含了所有寫操作,會更加便於redis的解析恢復。

劣勢

  1. 相同的資料,同一份資料,AOF比RDB大
  2. 針對不同的同步機制,AOF會比RDB慢,因為AOF每秒都會備份做寫操作,這樣相對與RDB來說就略低。 每秒備份fsync沒毛病,但是如果客戶端的每次寫入就做一次備份fsync 的話,那麼redis的效能就會下降。
  3. AOF發生過bug,就是資料恢復的時候資料不完整,這樣顯得AOF會比較脆弱,容易出現bug,因為AOF沒有RDB那麼簡單,但是呢為了防止bug的產生,AOF就不會根據日的指令去重構,而是根據當時快取中存在的資料指令去做重構,這樣就更加健壯和可靠了。

AOF的配置

# AOF 預設關閉,yes可以開啟
appendonly no

# A0F 的檔名
appendfilename "appendonly.aof"

# no∶不同步
# everySec∶每秒備份,推薦使用
# always∶每次操作都會備份,安全並且資料完整,但是慢效能差
appendfsync everysec

# 重寫的時候是否要同步,no可以保證資料安全
no-appendfsync-on-rewrite no

# 重寫機制∶避免檔案越來越大,自動優化壓縮指令,會fork一個新的程式去完成重寫動作,新程式裡的記憶體資料會被重寫,此時舊的aof檔案不會被讀取使用,類似rdb
# 當前A0F檔案的大小是上次AOF大小的100% 並且檔案體積達到64m,滿足兩者則觸發重寫
auto-aof-rewrite-percentage 100 
auto-aof-rewrite-min-size 64mb

到底採用RDB還是AOF呢?

  1. 如果你能接受一段時間的快取丟失,那麼可以使用RDB
  2. 如果你對實時性的資料比較care,那麼就用AOF
  3. 使用RDB和AOF結合一起做持久化,RDB做冷備,可以在不同時期對不同版本做恢復,AOF做熱備,保證資料僅僅只有1秒的損失。當AOF破損不可用了,那麼再用RDB恢復,這樣就做到了兩者的相互結合,也就是說Redis恢復會先載入AOF,如果AOF有問題會再載入RDB,這樣就達到冷熱備份的目的了。

Redis 快取過期處理與記憶體淘汰機制

計算機記憶體有限,越大越貴,Redis的高併發高效能都是基於記憶體的,用硬碟的話GG。

已過期的key如何處理?
設定了expire的key快取過期了,但是伺服器的記憶體還是會被佔用,這是因為redis所基於的兩種刪除策略。
redis有兩種策略∶

  1. (主動)定時刪除
    • 定時隨機的檢查過期的key,如果過期則清理刪除。(每秒檢查次數在redis.conf中的hz配置)
  2. (被動)惰性刪除
    • 當客戶端請求一個已經過期的key的時候,那麼redis會檢查這個key是否過期,如果過期了,則刪除,然後返回一個nil。這種策略對cpu比較友好,不會有太多的損耗,但是記憶體佔用會比較高。

所以,雖然key過期了,但是隻要沒有被redis清理,那麼其實記憶體還是會被佔用著的。

那麼如果記憶體被Redis快取佔用滿了咋辦?
記憶體佔滿了,可以使用硬碟,來儲存,但是沒意義,因為硬碟沒有記憶體快,會影響redis效能。所以,當記憶體佔用滿了以後,redis提供了一套快取淘汰機制∶ ME MORY MANAGEMENT。
maxmemory ∶當記憶體已使用率到達,則開始清理快取

* noeviction∶舊快取永不過期,新快取設定不了,返回錯誤
* allkeys-lru∶清除最少用的舊快取,然後儲存新的快取(推薦使用)
* allkeys-random∶在所有的快取中隨機刪除(不推薦)
* volatie-lru∶在那些設定了expire過期時間的快取中,清除最少用的舊快取,然後儲存新的快取
* volatile-random∶在那些設定了expire過期時間的快取中,隨機刪除快取
* volatile-ttl∶在那些設定了expire過期時間的快取中,刪除即將過期的

哨兵模式

Master掛了,如何保證可用性,實現繼續讀寫
什麼是哨兵?
Sentinel(哨兵)是用於監控Redis叢集中Master狀態的工具,是 Redis 高可用解決方案,哨兵可以監視一個或者多個redis master服務,以及這些master服務的所有從服務; 當某個master服務當機後,會把這個master下的某個從服務升級為master來替代已當機的master繼續工作。示例圖:

配置哨兵監控master
建立並且配置sentinel.conf∶

  • 普通配置
port 26379
pidfile "/usr/local/redis/sentinel/redis-sentinel.pid"
dir "/usr/local/redis/sentinel"
daemonize yes 
protected-mode no
logfile "/usr/local/redis/sentinel/redis-sentinel.1og"
  • 核心配置
# 配置哨兵
sentinel monitor mymaster 127.0.0.1 6379 2 
#密碼
sentinel auth-pass <master-name> <password>
# master被sentinel認定為失效的間隔時間
sentinel down-after-milliseconds mymaster 30000 
# 剩餘的slaves重新和新的master做同步的並行個數
sentinel parallel-syncs mymaster 1
# 主備切換的超時時間,哨兵要去做故障轉移,這個時候哨兵也是一個程式,如果他沒有去執行,超過這個時間後,會由其他的哨兵來處理
sentinel failover-timeout mymaster 180000

啟動哨兵x3
redis-sentinel sentinel.conf

測試

  1. master掛了,看slave是否成為master
  2. master恢復,觀察slave狀態

結論:master掛了以後,由於哨兵監控,剩餘slave會進行選舉,選舉後其中一個成為master,當原來的master恢復後,他會成為slave。

一般master資料無法同步給slave的方案檢查為如下∶

  1. 網路通訊問題,要保證互相ping通,內網互通。
  2. 關閉防火牆,對應的埠開放(虛擬機器中建議永久關閉防火牆,雲伺服器的話需要保證內網互通)。
  3. 統一所有的密碼,通過逐臺檢查機器以防某個節點被遺漏。

哨兵資訊檢查

檢視相關資訊

# 檢視reminis-master下的master節點資訊
sentinel master reminis-master

# 檢視reminis-master下的slaves節點資訊
sentinel slaves reminis-master

# 檢視reminis-master下的哨兵節點資訊
sentinel sentinels reminis-master

SpringBoot整合Redis哨兵-配置

配置如下:

spring:
  redis:
    database: 1 
    password: reminis 
    sentinel:
    master: reminis-master
    nodes: 192.168.32.10:26379,192.168.32.12:26379,192.168.32.13:26379

Redis叢集

前面我們一起學習了主從複製以及哨兵,他們可以提高讀的併發,但是單個master容量有限,資料達到一定程度會有瓶頸,這個時候可以通過水平擴充套件為多master-slave成為叢集。那麼這一節開始我們就一起來學習redis-cluster∶他可以支撐多個master-slave,支援海量資料,實現高可用與高併發。

哨兵模式其實也是一種叢集,他能夠提高讀請求的併發,但是容錯方面可能會有一些問題,比如master同步資料給slave的時候,這其實是非同步複製吧,這個時候master掛了,那麼slave上的資料就沒有master新,資料同步需要時間的,1-2秒的資料會丟失。master恢復並轉換成slave後,新資料則丟失。

特點:

  1. 每個節點知道彼此之間的關係,也會知道自己的角色,當然他們也會知道自己存在於一個叢集環境中,他們彼此之間可以互動和通訊,比如ping pong。那麼這些關係都會儲存到某個配置檔案中,每個節點都有,這個我們在搭建的時候需要做配置的。
  2. 客戶端要和叢集建立連線的話,只需要和其中一個建立關係就行。
  3. 某個節點掛了,也是通過超過半數的節點來進行的檢測,客觀下線後主從切換,和我們之前在哨兵模式中提到的是一個道理。
  4. Redis中存在很多的插槽,又可以稱之為槽節點,用於儲存資料,這個先不管,後面再說。

叢集容錯

構建Redis叢集,需要至少3個節點作為master,以此組成一個高可用的叢集,此外每個master都需要配備一個slave,所以整個叢集需要6個節點,這也是最經典的Redis叢集,也可以稱之為三主三從,容錯性更佳。所以在搭建的時候需要有6臺虛擬機器。請各自準備6臺虛擬機器,可以通過克隆去構建,使用單例項的Redis 去克隆即可。

  • 叢集也可以在單伺服器構建,稱之為偽叢集,但是生產環境肯定是真的,所以建議用6臺。
  • 克隆後務必關閉Redis。

構建Redis叢集

redis.conf 配置

# 開啟叢集模式
cluster-enabled yes

# 每一個節點需要有一個配置檔案,需要6份。每個節點處於叢集的角色都需要告知其他所有節點,彼此知道,這個檔案用於儲存叢集模式下的叢集狀態等資訊,這個檔案是由redis自己維護,我們不用管。如果你要重新建立叢集,那麼把這個檔案刪了就行
cluster-config-file nodes-201.conf 

# 超時時間,超時則認為master當機,隨後主備切換
cluster-node-timeout 5000 
# 開啟AOF
 appendonly yes

啟動6個redis例項

  1. 啟動6臺
  2. 如果啟動過程出錯,把rdb等檔案刪除清空

建立叢集

####
# 注意1∶如果你使用的是redis3.x版本,需要使用redis-trib.rb來構建叢集,最新版使用C語言來構建了,這個要注意
# 注意2∶以下為新版的redis構建方式
####

# 建立叢集,主節點和從節點比例為1,1-3為主,4-6為從,1和4.2和5 3和6分別對應為主從關係,這也是最經典用的最多的叢集模式
redis-cli --cluster create ip1:port1 ip2:port2 ip3:port 3 ip4:port4 ip5:port5 ip6:port6 --cluster-replicas 1

slots槽,用於裝資料,主節點有,從節點沒有

檢查叢集資訊:redis-cli--cluster check 192.168.25.64:6380

總結

最後,讓我們來看一下下方的思維導圖進行梳理內容:

複習

  1. 本階段開篇講述了分散式相關,其實分散式和叢集的概念在前期就介紹過了,不同的節點做著不同的事,就是分散式,不同的節點做著相同的事就是叢集。那麼Redis是NoSql,不僅僅是sql,功能更強勁,可以作為快取寫入記憶體,提供高速訪問,為資料庫做了一道屏障,保護資料庫,把熱點資料放入快取,從而提升專案的併發量與吞吐量。
  2. 介紹完Redis後我們又一起搭建了單機單例項版的Redis,需要注意,Redis雖然可以在win或mac上搭建,但是企業裡都是linux,所以我們一定要使用linux來搭建和配置。
  3. Redis提供命令列客戶端工具,也就是redis-cli進入命令列後可以進行相應的操作,我們講述了五大資料型別,分別為∶string,list,hash,set與zset。每個資料型別包含了一些操作指令,這些沒有必要去死記硬背,遇到了,就去查一下api,百度一下即可。
  4. Redis是單執行緒的,但是他的效能卻很高,在這裡我們講述了Redis的單執行緒模型,這一點往往在面試過程中會被問到。
  5. 當單機的Redis安裝配置完畢以後,我們整合到了專案中,結合了SpringBoot,優化了首頁的輪播圖與分類,因為這些完全可以放入快取,沒有必要去查詢資料庫。當然,對幹前期單體階段的購物車,我們結合了redis實現了分散式購物車,如此,不論使用者在任何電腦訪問,都能看到曾經的購物車資料,並且我們也實現了登入後的同步購物車功能。
  6. Redis可以實現類似於MQ的釋出與訂閱,是屬於生產者與消費者模式,但是正所謂專人做專事,釋出訂閱機制沒有必要用Redis來實現,企業裡都是使用的MQ。
  7. Redis的持久化機制,RDB與AOF,這兩種模式大家一定要知道他們之間的區別,一個是全量備份,一個是增量定時,各有各的好,也有缺點,面試過程中會被問到。
  8. 單機Redis存在單點故障與讀併發量的限制,所以可以通過主從與哨兵來實現,主從解決讀寫分離,並且一主多從能夠提升讀的併發。哨兵提供監控機制,一旦主掛了,備則上位成為主,如此實現高可用。
  9. 在Redis中可以設定無磁碟化,如果磁碟比較慢,可以開啟,但是一般來說,伺服器都會採用ssd,尤其針對資料儲存類的。
  10. 當key過期了,你會發現記憶體佔用率還是很高,這是因為redis的機制,有被動主動之分。這一點在面試中可能會被問到喲。此外,對於記憶體寫滿後的kev淘汰機制,我們也在這裡提到過,不同的策略都可以配置。
  11. Redis除了單機與哨兵模式外,還能搭建叢集,最經典的還屬三主三從,搭建完畢後我們還整合了SpringBoot,其實由於springboot的yml配置特性,大大的減少了配置項,如果你使用springmvc,xml中的配置會有很多,而yml中的配置也就2-3行的事。
  12. 對於快取來說,我們還需要預防快取穿透與雪崩,穿透的話一般來說只需要針對空值快取就行,過期時間設定5-10分鐘,這樣就流量就不會打在資料庫上導致當機當機。雪崩其實也可以做到提前預防,那就是用到過期時間的key,時間全部錯開,此外,有些資料可以做永久儲存的話那就直接儲存好了,這樣就不會造成大面積的key失效了。
  13. 最後有一點還需要說的,就是當一次請求過來,如果查詢的key比較多,能做到批量就批量,如果是迴圈查詢快取的話,一來吞吐量低,而來比較low。

相關文章