目錄
四.主從同步與對象模型
1.Redis 淘汰策略
2.Redis 如何做到?持久化
2.1 redis為什么要實現持久化
?2.2fork進程的寫時復制機制
?2.3大Key的影響
?2.4redis做持久化的方式
?2.5 aof
?2.6 rdb
?2.7 redis 持久化方式的優缺點
3.redis里面的高可用體現在哪里?
3.1redis? ?主從復制
?3.2Redis 哨兵模式(使用較少)
?3.3Redis cluster集群(重中之重)
四.主從同步與對象模型
1.Redis 淘汰策略
Redis 淘汰策略是指當 Redis 內存使用達到上限時,為了給新數據騰出空間,決定刪除哪些數據的規則 。主要有以下幾種:
針對設置過期時間鍵(volatile)的策略
volatile - lru(Least Recently Used,最近最少使用):在設置了過期時間的鍵中,淘汰最久未使用的鍵。通過記錄鍵的訪問時間,優先刪除長時間未被訪問的鍵,適用于需要定期清理過期緩存、希望保留熱門數據的場景 。比如電商網站緩存商品信息,可淘汰很久未被查看的商品緩存 。
volatile - lfu(Least Frequently Used,最少頻率使用)?:使用 LFU 算法,在設置了過期時間的鍵里,淘汰訪問頻率最低的鍵。能更好保留高頻訪問數據,適用于有明顯訪問頻率差異且關注過期數據清理的場景,如新聞資訊類應用,淘汰很少被點擊的新聞緩存 。
volatile - ttl:在設置了過期時間的鍵中,優先淘汰過期時間(TTL)最短的鍵,即那些最近要過期的鍵。適合時效性敏感數據場景,如驗證碼、臨時會話緩存 ,可及時清理即將失效數據。
volatile - random:在設置了過期時間的鍵中隨機選擇淘汰的鍵。適用于不太關注數據訪問頻率和過期先后順序,僅需淘汰過期數據的場景 。
針對所有鍵(allkeys)的策略
allkeys - lru:對所有鍵(無論是否設置過期時間),使用 LRU 算法淘汰最久未使用的鍵。廣泛用于緩存場景,能確保經常被訪問的熱點數據留在內存中,提高緩存命中率 ,像熱門游戲道具緩存。
allkeys - lfu:使用 LFU 算法淘汰所有鍵中訪問頻率最低的鍵。適用于緩存和內存使用情況需動態調整,且有長尾訪問分布、需要識別熱點數據的場景 。
allkeys - random:從所有鍵中隨機淘汰一些鍵。適用于不關注數據訪問頻率和時效性,數據權重和重要性相對均衡的場景 。
禁止淘汰策略
no - eviction:當內存達到最大限制時,不淘汰任何數據,同時拒絕新的寫入請求(包括插入和更新操作),但讀請求可繼續。適合對數據完整性要求極高、不允許丟失數據的關鍵場景 ,如金融交易記錄存儲,但需確保系統有足夠內存 。
2.Redis 如何做到?持久化
2.1 redis為什么要實現持久化
redis屬于內存型數據庫
redis 的數據全部在內存中,如果突然宕機,數據就會全部丟 失,因此需要持久化來保證 Redis 的數據不會因為故障而丟失, redis 重啟的時候可以重新加載持久化文件來恢復數據;
?2.2fork進程的寫時復制機制
fork頁表復制,共用同一塊物理內存
父進程對對數據修改時,觸發寫保護中斷,從而進行物理內存的復制
子進程的頁表指向舊的物理內存
父進程的頁表指向新的物理內存
在發生寫的操作的時候,系統才會去復制物理內存
避免物理內存的復制時間過長導致父進程長時間阻塞
?2.3大Key的影響
在key value中 如果value 占用大量空間就是大key
比如v是hash,zset中存儲大量元素
大 Key 會導致 Redis 性能下降、操作耗時、網絡擁塞、內存占用不合理、影響持久化與數據遷移等問題,危害 Redis 穩定性和可用性。
?2.4redis做持久化的方式
###### aof ######
# redis.cnf
appendonly no
appendfilename "appendonly.aof"
# aof read write ? invert
# appendfsync always
appendfsync everysec
# appendfsync no
# auto-aof-rewrite-percentage 為 0 則關閉 aof 復寫
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# yes 如果 aof 數據不完整,盡量讀取最多的格式正確的數據;
# no 如果 aof 數據不完整 報錯,可以通過 redis-checkaof 來修復 aof 文件;
aof-load-truncated yes
# 開啟混合持久化
aof-use-rdb-preamble yes
###### rdb ######
# save ""
# save 3600 1
# save 300 100
# save 60 10000
redis通常使用aof或者rdb方式做數據的持久化
默認配置下,只開啟 rdb 持久化;
?2.5 aof
a ppend o nly f ileaof 日志存儲的是 Redis 服務器的順序指令序列, aof 日志只記錄對內存修改的指令記錄;
?aof
這是 Redis 中 AOF(Append - Only - File )持久化方式的三種寫回策略:
always:主線程執行寫命令后,立即將 AOF 日志 fsync 到磁盤 。此策略數據安全性最高,能保證最多丟失一個寫命令數據,但頻繁磁盤 I/O 操作會降低 Redis 性能。
every_sec:主線程執行寫命令后,將寫操作寫入 AOF 緩沖區,由后臺線程(bio_fsync_aof )每秒執行一次 fsync 將緩沖區內容刷盤 。兼顧性能與數據安全性,最多丟失 1 秒數據,是常用策略。
no:主線程執行寫命令后,將寫操作寫入 AOF 緩沖區,不主動觸發 fsync,由操作系統決定何時將緩沖區內容刷盤 。性能最佳,但在系統崩潰或斷電時,可能丟失大量數據
?aof-rewrite
目的
AOF 重寫(aof - rewrite)是為解決 AOF 文件過大問題。AOF 文件記錄 Redis 寫操作,長期積累會變得龐大,導致數據恢復速度變慢,重寫可縮減其體積,提升恢復效率?
工作原理
Redis 調用?
fork
?函數創建子進程。子進程基于當前內存中的數據狀態,重新構建 AOF 文件內容。在此過程中,會去除對同一 Key 的冗余操作記錄。例如,多次對同一 Key 進行修改,重寫時只保留最終有效操作,減少文件大小 。在子進程進行 AOF 重寫期間,主線程仍正常處理寫操作。這些寫操作會被記錄到一個重寫緩沖區。當子進程完成 AOF 重寫后,主線程會將重寫緩沖區中的內容追加到新生成的 AOF 文件末尾,保證數據的一致性 。
?2.6 rdb
rdb
fork 子進程進行持久化:Redis 利用?
fork
?系統調用創建一個子進程。父進程(Redis 主進程)繼續處理客戶端請求,子進程負責將當前 Redis 內存中的數據快照寫入磁盤。這樣做的好處是主進程不會被磁盤 I/O 操作阻塞,保證 Redis 服務在持久化期間仍能對外提供服務 。
基于內存中(所有數據)對象編碼直接持久化:RDB 會按照 Redis 數據在內存中的對象編碼方式,直接將所有數據以二進制格式保存到磁盤文件中。比如字符串、哈希、列表等不同數據結構,都依據其在內存中的編碼規則進行持久化存儲 。生成的 RDB 文件緊湊,占用磁盤空間相對較小,恢復數據時速度較快,適合用于備份、災難恢復等場景
?rdb-aof混用
寫操作緩沖與追加:在 RDB 持久化期間,Redis 主線程正常處理的寫操作,會被記錄到一個重寫緩沖區。當子進程完成 RDB 文件生成后,主線程會把重寫緩沖區中的內容追加到 AOF 文件末尾。這樣既利用了 RDB 文件緊湊、恢復快的優勢,又通過 AOF 追加后續寫操作,保證數據的完整性,減少數據丟失風險?
?2.7 redis 持久化方式的優缺點
aof?
優點:數據可靠,丟失較少,持久化過程代價比較低
缺點:aof文件過大,數據恢復慢
rdb
優點:rdb文件小,數據恢復快
缺點:數據丟失多,持久化過程代價比較高
所以我們需要采用?aof-rewrite 和?rdb-aof混用 來對持久化方式進行優化
3.redis里面的高可用體現在哪里?
3.1redis? ?主從復制
主要用來實現 redis 數據的可靠性;防止主 redis 所在磁盤損壞,造成數據永久丟失;主從之間采用異步復制的方式;

異步復制
全量數據同步:從節點(replica)初次連接主節點(master)或與主節點斷開連接后重新連接時,會進行全量數據同步。主節點將自身的所有數據發送給從節點,從節點接收并加載這些數據,以此來和主節點數據保持一致 。
增量數據同步:在全量同步完成后,主節點后續產生的寫操作會以增量形式發送給從節點。主節點將寫命令發送給從節點執行,使從節點數據能隨著主節點變化而更新 。
可能帶來數據不一致:由于異步復制中,主節點執行寫操作后無需等待從節點確認就繼續處理其他請求,若主節點在向從節點發送增量數據前發生故障,就可能導致部分從節點數據和主節點不一致 。
環形緩沖區、復制偏移量
環形緩沖區:主節點會維護一個環形緩沖區來記錄寫操作命令。它是一個固定大小的緩沖區,新的寫操作命令會覆蓋最早的命令(當緩沖區滿時 )。環形緩沖區為從節點增量同步提供數據來源 。
復制偏移量:主從節點都會維護一個復制偏移量。主節點每執行一個寫操作,偏移量就會增加;從節點接收并執行主節點發送的寫操作后,也會更新自己的偏移量。復制偏移量用于標識數據同步的位置,在網絡故障等情況恢復后,從節點可依據偏移量與主節點進行數據同步 。
runid
runid 是 Redis 實例啟動時生成的唯一隨機 ID 。在主從復制中,主節點的 runid 會發送給從節點,從節點將其保存,用于標識主從映射關系。當從節點與主節點重新連接時,會通過 runid 確認是否還是原來的主節點 。
主從復制作用
單點故障:主從復制可以在一定程度上解決單點故障問題。當主節點出現故障時,可將從節點提升為主節點繼續提供服務,減少服務中斷時間 。
可用性的基礎:主從復制為 Redis 服務的可用性提供了基礎保障。從節點可以分擔讀請求,提高系統的并發處理能力;同時在主節點故障時可切換,保證服務的連續性 。
注意事項
建立連接:replica 必須主動向 master 建立連接,否則無法新增 replica 。這是因為 Redis 的主從復制機制設計為從節點主動發起連接請求,主節點被動接受連接并提供數據同步 。
拉取數據:replica 主動向 master 拉取數據。在網絡出現問題后,replica 保存有同步位置(通過復制偏移量 ),當網絡恢復時,可依據該位置繼續從 master 拉取數據,實現斷點續傳式的數據同步 。
?
replica主動向master建立連接并從中拉取數據
?3.2Redis 哨兵模式(使用較少)
哨兵模式是 Redis 可用性的解決方案;它由一個或多個 sentinel實例構成 sentinel 系統;該系統可以監視任意多個主庫以及這些主庫所屬的從庫;當主庫處于下線狀態,自動將該主庫所屬的某個從庫升級為新的主庫;客戶端來連接集群時,會首先連接 sentinel ,通過 sentinel 來查詢主節點的地址,并且通過 subscribe 監聽主節點切換,然后再連接主節點進行數據交互。當主節點發生故障時, sentinel 主動推送新的主庫地址。通過這樣客戶端無須重啟即可自動完成節點切換。哨兵模式當中涉及多個選舉流程采用的是 Raft 算法的領頭選舉方法的實現;
哨兵模式流程
主觀下線:哨兵節點會定期向主節點和從節點發送心跳檢測命令。如果在規定時間內未收到主節點的響應,該哨兵節點會將主節點標記為 “主觀下線”,即從自身視角判斷主節點出現問題 。
客觀下線:當一個哨兵節點將主節點標記為主觀下線后,它會與其他哨兵節點進行通信,交換對主節點狀態的判斷。當判斷主節點下線的哨兵節點數量達到一定閾值(配置文件中設定 ),就會將主節點標記為 “客觀下線”,即大家公認主節點已無法正常工作 。
哨兵選舉:在確認主節點客觀下線后,哨兵節點之間會進行選舉,選出一個 “領導者” 哨兵節點。選舉一般基于 Raft 算法等分布式選舉算法,獲得多數投票的哨兵節點成為領導者 。
從庫選主:當選出的領導者哨兵節點會從可用的從節點中挑選一個來晉升為主節點。挑選依據包括從節點的優先級(可在配置文件中設置 )、復制偏移量(偏移量越大表示數據越新 )等因素 。
故障轉移:確定新主節點后,領導者哨兵節點會指揮其他從節點去連接新主節點,并開始從新主節點進行數據復制。同時,會將原主節點標記為已下線,當它恢復后將作為新主節點的從節點 。
如何使用
連接哨兵節點:客戶端首先需要連接到一個或多個哨兵節點,獲取關于主從節點的相關信息 。
獲取主節點地址,并連接:客戶端從哨兵節點處獲取當前主節點的地址信息,然后直接連接到主節點進行數據讀寫操作 。
發起發布訂閱連接,監聽主節點遷移信息:客戶端與哨兵節點建立發布訂閱連接,以便在主節點發生故障轉移、遷移時,能夠及時收到通知,更新連接的主節點地址 。
缺點
部署麻煩:相比簡單的主從復制模式,哨兵模式需要部署多個哨兵節點,涉及節點配置、網絡配置等多方面工作,增加了運維成本和復雜度 。
沒有避免數據丟失問題:在主節點發生故障時,若部分從節點還未完全同步主節點數據,故障轉移后可能導致這部分數據丟失 。比如異步復制場景下,主節點新寫的數據還沒來得及同步給從節點就故障了 。
沒有數據擴展機制:哨兵模式主要解決的是主節點高可用問題,并沒有提供數據分片、擴展存儲容量等機制,當數據量增長時難以滿足需求 。
幾十秒:這里可能指故障轉移的時間,一般在幾十秒左右。雖然能實現自動故障轉移,但幾十秒的服務中斷時間在一些對可用性要求極高的場景下可能無法接受?
?3.3Redis cluster集群(重中之重)
Redis cluster 將所有數據劃分為 16384 個槽位,每個 redis 節點負責其中一部分槽位。 cluster 集群是一種 去中心化 的 集群方式;
如圖,該集群由三個 redis 節點組成,每個節點負責整個集群的一部分數據,每個節點負責的數據多少可能不一樣。這三個 節點 相互連接組成一個 對等的集群 ,它們之間通過一種特殊的二
進制協議交互集群信息;當 redis cluster 的客戶端來連接集群時,會得到一份集群的槽位配置信息。這樣當客戶端要查找某個 key 時,可以直接定位到目標節點。客戶端為了可以 直接定位 (對 key 通過 crc16 進行 hash 再對2的14次方取余)某個具體的 key 所在節點,需要緩存槽位相關信息,這樣才可以準確快速地定位到相應的節點。同時因為可能會存在客戶端與服務器存儲槽位的信息不一致的情況,還需要 糾正機制 (通過返回 - MOVED 3999 127.0.0.1:6479 ,客戶端收到后需要立即糾正本地的槽位映射表)來實現槽位信息的校驗調整。另外, redis cluster 的每個節點會將集群的配置信息持久化到配置文件中,這就要求確保配置文件是可寫的,而且盡量不要依靠人工修改配置文件;下圖來源于網絡;盡量使三個主節點的數據均衡;分布式一致性 hash
?集群配置
創建六個文件夾分別為7001 7002 7003 7004 7005 7006?
每個文件夾里面的.conf文件內容設置如下 編號對標即可
設置start.sh文件并授權
啟動start.sh文件
智能創建集群?
主:7001 從:7006
主:7002 從:7004
主:7003 從:7005
配置成功
測試
補充:
主節點如果宕機 從節點會替換過去
Redis 集群中主節點宕機后,從節點經故障檢測與選舉成為新主節點,丟棄舊緩存、更新集群狀態,通過持久化恢復及后續復制同步數據,保障數據一致性,也可手動觸發從節點替換主節點。