Redis RDB 持久化原理
1)RDB 持久化配置
# 時間策略,表示900s內如果有1條是寫入命令,就觸發產生一次快照,可以理解為就進行一次備份 save 900 1 save 300 10 # 表示300s內有10條寫入,就產生快照 save 60 10000 # 表示60s內有10000條寫入,就產生快照 # 文件名稱 dbfilename dump.rdb # 如果持久化出錯,主進程是否停止寫入 stop-writes-on-bgsave-error yes # 是否壓縮 rdbcompression yes # 導入時是否檢查 rdbchecksum yes # 文件保存路徑 dir /usr/local/redis-4.0.6
2)save 的含義
實際生產環境每個時段的讀寫請求肯定不是均衡的,為此 redis 提供一種根據 key 單位時間操作次數來觸發一次備份到磁盤,我們可以自由定制什么情況下觸發備份,此功能起到平衡性能與數據安全的作用
3)在 Redis 中 RDB 持久化的觸發分為兩種:自己手動觸發與 Redis 定時觸發
針對 RDB 方式的持久化,手動觸發可以使用:
- save:會阻塞當前 Redis 服務器,直到持久化完成,線上應該禁止使用。
- bgsave:該觸發方式會 fork 一個子進程,由子進程負責持久化過程,因此阻塞只會發生在 fork 子進程的時候
而自動觸發的場景主要是有以下幾點:
- 根據我們的 save m n 配置規則自動觸發
- 從節點全量復制時,主節點發送 rdb 文件給從節點完成復制操作,主節點會觸發 bgsave
- 執行 debug reload 時
- 執行 shutdown 時,如果沒有開啟aof,也會觸發
4)禁用RDB
只需要在 save 的最后一行寫上:save ""
Redis AOF 持久化原理
1)AOF 持久化配置
# 是否開啟aof appendonly yes # 文件名稱 appendfilename "appendonly.aof" # 同步方式 appendfsync everysec # aof重寫期間是否同步 no-appendfsync-on-rewrite no # 重寫觸發配置 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 加載aof時如果有錯如何處理 aof-load-truncated yes # yes表示如果aof尾部文件出問題,寫log記錄並繼續執行。no表示提示寫入等待修復后寫入 # 文件重寫策略 aof-rewrite-incremental-fsync yes
2)appendfsync 同步模式有三種模式,一般情況下都采用 everysec 配置,在數據和安全里面做平衡性選擇,最多損失1s的數據
- always:把每個寫命令都立即同步到 aof,很慢,但是很安全
- everysec:每秒同步一次,是折中方案
- no:redis 不處理交給 OS 來處理,非常快,但是也最不安全
3)AOF 的整個流程大體來看可以分為兩步
第一步是命令的實時寫入(如果是 appendfsync everysec 配置,會有 1s 損耗)。
第二步是對 aof 文件的重寫。
步驟:
命令寫入=》追加到 aof_buf =》通過時間事件調用 flushAppendOnlyFile 函數同步到 aof 磁盤
原因:
實時寫入磁盤會帶來非常高的磁盤 IO,影響整體性能
4)AOF 持久化的效率和安全性分析
- always:每個時間事件循環都將 AOF_BUF 緩沖區的所有內容寫入到 AOF 文件,並且同步 AOF 文件,這是最安全的方式,但磁盤操作和阻塞延遲,是 IO 開支較大。
- everysec:每秒同步一次,性能和安全都比較中庸的⽅方式,也是 redis 推薦的方式。如果遇到物理服務器故障,有可能導致最近一秒內 aof 記錄丟失(可能為部分丟失)。
- no:redis 並不直接調用文件同步,而是交給操作系統來處理,操作系統可以根據 buffer 填充情況/通道空閑時間等擇機觸發同步;這是一種普通的文件操作方式。性能較好,在物理服務器故障時,數據丟失量會因 OS 配置有關。處於 no 模式下的 flushAppendOnlyFile 調用無須執行同步操作
Redis 兩種持久化方案對比
Redis 提供了不同的持久性選項:
- RDB 持久性以指定的時間間隔執行數據集的時間點快照。
- AOF 持久性記錄服務器接收的每個寫入操作,將在服務器啟動時再次播放,重建原始數據集。使用與 Redis 協議本身相同的格式以僅追加方式記錄命令。當 Redis 太大時,Redis 能夠重寫日志背景。
RDB 的優缺點
優點:
- RDB 最大限度地提高了 Redis 的性能,父進程不需要參與磁盤 I/O
- 與 AOF 相比,RDB 允許使用大數據集更快地重啟
缺點:
- 如果您需要在 Redis 停止工作時(例如斷電后)將數據丟失的可能性降至最低,則 RDB 並不好
- RDB 經常需要 fork() 才能使用子進程持久存儲在磁盤上。如果數據集很大,fork() 可能會非常耗時
AOF 的優缺點
優點:
- 數據更加安全
- 當 Redis AOF 文件太大時,Redis 能夠在后台自動重寫 AOF
- AOF 以易於理解和解析的格式一個接一個地包含所有操作的日志
缺點:
- AOF 文件通常比同一數據集的等效 RDB 文件大
- 根據確切的fsync策略,AOF 可能比 RDB 慢
RDB 和 AOF,我應該用哪一個?
一般來說,如果想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。如果你非常關心你的數據,但仍然可以承受數分鍾以內的數據丟失,那么你可以只使用 RDB 持久化。有很多用戶都只使用 AOF 持久化, 但我們並不推薦這種方式:因為定時生成 RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。
在線上我們到底該怎么做?
- RDB 持久化與 AOF 持久化同步使用
- 如果 Redis 中的數據並不是特別敏感或者可以通過其它方式重寫生成數據,可以關閉持久化,如果丟失數據可以通過其它途徑補回
- 自己制定策略定期檢查 Redis 的情況,然后可以手動觸發備份、重寫數據
- 采用集群和主從同步
Redis 過期 key 清除策略
Redis 如何淘汰過期的 keys?
惰性刪除 :
概念:當一些客戶端嘗試訪問它時,key 會被發現並主動的過期。放任鍵過期不管,但是每次從鍵空間中獲取鍵時,都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵
特點:CPU 友好,但如果一個 key 不再使用,那么它會一直存在於內存中,造成浪費
定時刪除:
概念:設置鍵的過期時間的同時,創建一個定時器(timer),讓定時器在鍵的過期時間來臨時,立即執行對鍵的刪除操作
定期刪除:
隔一段時間,程序就對數據庫進行一次檢查,刪除里面的過期鍵,至於要刪除多少過期鍵,以及要檢查多少個數據庫,則由算法決定。 即設置一個定時任務,比如10分鍾刪除一次過期的 key;間隔小則占用 CPU,間隔大則浪費內存
例如 Redis 每秒處理:
- 測試隨機的 20 個 keys 進⾏行行相關過期檢測。
- 刪除所有已經過期的 keys。
- 如果有多於 25% 的 keys 過期,重復步奏1
Redis 服務器實際使用的是惰性刪除和定期刪除兩種策略:通過配合使用這兩種刪除策略,服務器可以很好地在合理使用 CPU 時間和避免浪費內存空間之間取得平衡。
惰性刪除策略是怎么實現?
通過 expireIfNeeded 函數,當我們操作 key 的時候進行判斷 key 是否過期。
定期刪除策略是怎么實現的?
通過 activeExpireCycle 函數,serverCron 函數執行時,activeExpireCycle 函數就會被調用,規定的時間里面分多次遍歷服務器的 expires 字典隨機檢查一部分 key 的過期時間,並刪除其中的過期 key。