Redis的持久化機制
RDB: Redis DataBase
-
什麼是RDB
RDB∶每隔一段時間,把內存中的數據寫入磁盤的臨時文件,作爲快照,恢復的時候把快照文件讀進內存。如果宕機重啓,那麼內存裏的數據肯定會沒有的,那麼再次啓動redis後,則會恢復。 -
備份與恢復
內存備份-->磁盤臨時文件
臨時文件-->恢復到內存 -
RDB優劣勢
- 優勢
- 每隔一段時間備份,全量備份
- 災備簡單,可以遠程傳輸
- 子進程備份的時候,主進程不會有任何io操作(不會有寫入修改或刪除),保證備份數據的的完整性
- 相對AOF來說,當有更大文件的時候可以快速重啓恢復
- 劣勢
- 發生故障時,有可能會丟失最後一次的備份數據
- 子進程所佔用的內存比會和父進程一模一樣,這會造成CPU負擔
- 由於定時全量備份是重量級操作,所以對於實時備份,就無法處理了。
- 優勢
-
RDB的配置
- 保存位置,可以在redis.conf自定義∶
/user/local/redis/working/dump.rdb
- 保存機制∶
- 保存位置,可以在redis.conf自定義∶
save 900 1 # 如果1個緩存更新,則15分鐘後備份
save 300 10 # 如果10個緩存更新,則5分鐘後備份
save 60 10000 # 如果10000個緩存更新,則1分鐘後備份
- stop-writes-on-bgsave-error
- yes∶如果save過程出錯,則停止寫操作
- no∶ 可能造成數據不一致
- rdbcompression
- yes∶開啓rdb壓縮模式
- no∶關閉,會節約cpu損耗,但是文件會大,道理同nginx
- rdbchecksum
- yes∶使用CRC64算法校驗對rdb進行數據校驗,有10%性能損耗
- no∶不校驗
總結
RDB適合大量數據的恢復,但是數據的完整性和一致性可能會不足
AOF: Append Only File
RDB會丟失最後一次備份的rdb文件,但是其實也無所謂,其實也可以忽略不計,畢竟是緩存,丟了就丟了,但是如果追求數據的完整性,那就的考慮使用AOF了。
AOF特點
- 以日誌的形式來記錄用戶請求的寫操作。讀操作不會記錄,因爲寫操作纔會存存儲。
- 文件以追加的形式而不是修改的形式。
- redis的aof恢復其實就是把追加的文件從開始到結尾讀取執行寫操作。
優勢
- AOF更加耐用,可以以秒級別爲單位備份,如果發生問題,也只會丟失最後一秒的數據,大大增加了可靠性和數據完整性。所以AOF可以每秒備份一次,使用fsync操作。
- 以log日誌形式追加,如果磁盤滿了,會執行redis-check-aof 工具
- 當數據太大的時候,redis可以在後臺自動重寫aof。當redis繼續把日誌追加到老的文件中去時,重寫也是非常安全的,不會影響客戶端的讀寫操作。
- AO日誌包含了所有寫操作,會更加便於redis的解析恢復。
劣勢
- 相同的數據,同一份數據,AOF比RDB大
- 針對不同的同步機制,AOF會比RDB慢,因爲AOF每秒都會備份做寫操作,這樣相對與RDB來說就略低。 每秒備份fsync沒毛病,但是如果客戶端的每次寫入就做一次備份fsync 的話,那麼redis的性能就會下降。
- 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呢?
- 如果你能接受一段時間的緩存丟失,那麼可以使用RDB
- 如果你對實時性的數據比較care,那麼就用AOF
- 使用RDB和AOF結合一起做持久化,RDB做冷備,可以在不同時期對不同版本做恢復,AOF做熱備,保證數據僅僅只有1秒的損失。當AOF破損不可用了,那麼再用RDB恢復,這樣就做到了兩者的相互結合,也就是說Redis恢復會先加載AOF,如果AOF有問題會再加載RDB,這樣就達到冷熱備份的目的了。
Redis 緩存過期處理與內存淘汰機制
計算機內存有限,越大越貴,Redis的高併發高性能都是基於內存的,用硬盤的話GG。
已過期的key如何處理?
設置了expire的key緩存過期了,但是服務器的內存還是會被佔用,這是因爲redis所基於的兩種刪除策略。
redis有兩種策略∶
- (主動)定時刪除
- 定時隨機的檢查過期的key,如果過期則清理刪除。(每秒檢查次數在redis.conf中的hz配置)
- (被動)惰性刪除
- 當客戶端請求一個已經過期的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
測試
- master掛了,看slave是否成爲master
- master恢復,觀察slave狀態
結論:master掛了以後,由於哨兵監控,剩餘slave會進行選舉,選舉後其中一個成爲master,當原來的master恢復後,他會成爲slave。
一般master數據無法同步給slave的方案檢查爲如下∶
- 網絡通信問題,要保證互相ping通,內網互通。
- 關閉防火牆,對應的端口開放(虛擬機中建議永久關閉防火牆,雲服務器的話需要保證內網互通)。
- 統一所有的密碼,通過逐臺檢查機器以防某個節點被遺漏。
哨兵信息檢查
查看相關信息
# 查看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後,新數據則丟失。
特點:
- 每個節點知道彼此之間的關係,也會知道自己的角色,當然他們也會知道自己存在於一個集羣環境中,他們彼此之間可以交互和通信,比如ping pong。那麼這些關係都會保存到某個配置文件中,每個節點都有,這個我們在搭建的時候需要做配置的。
- 客戶端要和集羣建立連接的話,只需要和其中一個建立關係就行。
- 某個節點掛了,也是通過超過半數的節點來進行的檢測,客觀下線後主從切換,和我們之前在哨兵模式中提到的是一個道理。
- 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實例
- 啓動6臺
- 如果啓動過程出錯,把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
總結
最後,讓我們來看一下下方的思維導圖進行梳理內容:
複習
- 本階段開篇講述了分佈式相關,其實分佈式和集羣的概念在前期就介紹過了,不同的節點做着不同的事,就是分佈式,不同的節點做着相同的事就是集羣。那麼Redis是NoSql,不僅僅是sql,功能更強勁,可以作爲緩存寫入內存,提供高速訪問,爲數據庫做了一道屏障,保護數據庫,把熱點數據放入緩存,從而提升項目的併發量與吞吐量。
- 介紹完Redis後我們又一起搭建了單機單實例版的Redis,需要注意,Redis雖然可以在win或mac上搭建,但是企業裏都是linux,所以我們一定要使用linux來搭建和配置。
- Redis提供命令行客戶端工具,也就是redis-cli進入命令行後可以進行相應的操作,我們講述了五大數據類型,分別爲∶string,list,hash,set與zset。每個數據類型包含了一些操作指令,這些沒有必要去死記硬背,遇到了,就去查一下api,百度一下即可。
- Redis是單線程的,但是他的性能卻很高,在這裏我們講述了Redis的單線程模型,這一點往往在面試過程中會被問到。
- 當單機的Redis安裝配置完畢以後,我們整合到了項目中,結合了SpringBoot,優化了首頁的輪播圖與分類,因爲這些完全可以放入緩存,沒有必要去查詢數據庫。當然,對幹前期單體階段的購物車,我們結合了redis實現了分佈式購物車,如此,不論用戶在任何電腦訪問,都能看到曾經的購物車數據,並且我們也實現了登錄後的同步購物車功能。
- Redis可以實現類似於MQ的發佈與訂閱,是屬於生產者與消費者模式,但是正所謂專人做專事,發佈訂閱機制沒有必要用Redis來實現,企業裏都是使用的MQ。
- Redis的持久化機制,RDB與AOF,這兩種模式大家一定要知道他們之間的區別,一個是全量備份,一個是增量定時,各有各的好,也有缺點,面試過程中會被問到。
- 單機Redis存在單點故障與讀併發量的限制,所以可以通過主從與哨兵來實現,主從解決讀寫分離,並且一主多從能夠提升讀的併發。哨兵提供監控機制,一旦主掛了,備則上位成爲主,如此實現高可用。
- 在Redis中可以設置無磁盤化,如果磁盤比較慢,可以打開,但是一般來說,服務器都會採用ssd,尤其針對數據存儲類的。
- 當key過期了,你會發現內存佔用率還是很高,這是因爲redis的機制,有被動主動之分。這一點在面試中可能會被問到喲。此外,對於內存寫滿後的kev淘汰機制,我們也在這裏提到過,不同的策略都可以配置。
- Redis除了單機與哨兵模式外,還能搭建集羣,最經典的還屬三主三從,搭建完畢後我們還整合了SpringBoot,其實由於springboot的yml配置特性,大大的減少了配置項,如果你使用springmvc,xml中的配置會有很多,而yml中的配置也就2-3行的事。
- 對於緩存來說,我們還需要預防緩存穿透與雪崩,穿透的話一般來說只需要針對空值緩存就行,過期時間設置5-10分鐘,這樣就流量就不會打在數據庫上導致死機宕機。雪崩其實也可以做到提前預防,那就是用到過期時間的key,時間全部錯開,此外,有些數據可以做永久保存的話那就直接保存好了,這樣就不會造成大面積的key失效了。
- 最後有一點還需要說的,就是當一次請求過來,如果查詢的key比較多,能做到批量就批量,如果是循環查詢緩存的話,一來吞吐量低,而來比較low。