13.redis持久化-RDB
阿新 • • 發佈:2022-05-25
reids的持久化是重點
reids是記憶體資料庫,如果不講記憶體中的資料儲存到磁碟上,那麼服務一旦出了問題,伺服器中的資料庫狀態也會消失,所以redis提供了持久化!
RDB
在redis.conf配置檔案中配置了rdb檔案的持久化規則在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,也就是行話講的Snapshot快照,它恢復時是將快照中檔案直接讀到記憶體中 Redis會到哪都建立(fork),一個子程序來進行持久化,會將資料寫入一個臨時的檔案中,等到持久化過程都結束了,再用這個臨時 檔案替換上次持久化好的檔案。整個過程中,主程序不進行任何的io操作,這就確保了極高的效能。如果需要進行大規模的資料恢復 且對於資料的恢復完整性不是非常的敏感,那麼RDB方式比AOF方式更加的高效,RDB的缺點時最後一次持久化後的資料可能會丟失 我們預設使用的是RDB,一般情況下不需要修改整個配置! RDB儲存的檔案是:dump.rdb 因為在redis.conf配置檔案中配置了rdb的預設檔名稱 dbfilename dump.rdb
save 900 1:表示900 秒內如果至少有 1 個 key 的值變化,則儲存 save 300 10:表示300 秒內如果至少有 10 個 key 的值變化,則儲存 save 60 10000:表示60 秒內如果至少有 10000 個 key 的值變化,則儲存 1.在互動模組獲取rdb檔案的儲存路徑 127.0.0.1:6379> config get dir 1) "dir" 2) "/data" 127.0.0.1:6379> config get save 1) "save" 2) "60 5"------>意思是60秒內有5個key的值發生了變化,就會觸發持久化規則,生成dump.rdb檔案 127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> set k2 v2 OK 127.0.0.1:6379> set k3 v3 OK 127.0.0.1:6379> set k4 v4 OK 127.0.0.1:6379> set k5 v5 OK 會在docker容器的/data目錄下生成:dump.rdb檔案
RDB 有兩種觸發方式,分別是自動觸發和手動觸發
1.自動觸發 在配置檔案中配置save策略 2.手動觸發 手動觸發Redis進行RDB持久化的命令有兩種: 2.1 1、save 該命令會阻塞當前Redis伺服器,執行save命令期間,Redis不能處理其他命令,直到RDB過程完成為止。 顯然該命令對於記憶體比較大的例項會造成長時間阻塞,這是致命的缺陷,為了解決此問題,Redis提供了第二種方式 當執行save時,會直接生成dump.rdb檔案 2.2 bgsave 執行該命令時,Redis會在後臺非同步進行快照操作,快照同時還可以響應客戶端請求。 具體操作是Redis程序執行fork操作建立子程序,RDB持久化過程由子程序負責,完成後自動結束。阻塞只發生在fork階段,一般時間很短。 基本上 Redis 內部所有的RDB操作都是採用 bgsave 命令。 ps:執行執行 flushall 命令,也會產生dump.rdb檔案,但裡面是空的.
恢復資料
將備份檔案 (dump.rdb) 移動到 redis 安裝目錄並啟動服務即可,redis就會自動載入檔案資料至記憶體了。Redis 伺服器在載入 RDB 檔案期間,會一直處於阻塞狀態,直到載入工作完成為止。
停止 RDB 持久化
在redis的客戶端上:使用命令將save策略置為空
config set save " "
RDB 的優勢和劣勢
①、優勢
1.RDB是一個非常緊湊(compact)的檔案,它儲存了redis 在某個時間點上的資料集。這種檔案非常適合用於進行備份和災難恢復。
2.生成RDB檔案的時候,redis主程序會fork()一個子程序來處理所有儲存工作,主程序不需要進行任何磁碟IO操作。
3.RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。
②、劣勢
1、RDB方式資料沒辦法做到實時持久化/秒級持久化。因為bgsave每次執行都要執行fork操作建立子程序,屬於重量級操作,如果不採用壓縮演算法(記憶體中的資料被克隆了一份,大致2倍的膨脹性需要考慮),頻繁執行成本過高(影響效能)
2、RDB檔案使用特定二進位制格式儲存,Redis版本演進過程中有多個格式的RDB版本,存在老版本Redis服務無法相容新版RDB格式的問題(版本不相容)
3、在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最後一次快照後的所有修改(資料有丟失)
RDB 自動儲存的原理
Redis有個伺服器狀態結構:
struct redisService{
//1、記錄儲存save條件的陣列
struct saveparam *saveparams;
//2、修改計數器
long long dirty;
//3、上一次執行儲存的時間
time_t lastsave;
}
1、首先看記錄儲存save條件的陣列 saveparam,裡面每個元素都是一個 saveparams 結構:
struct saveparam{
//秒數
time_t seconds;
//修改數
int changes;
};
前面我們在 redis.conf 配置檔案中進行了關於save 的配置:
save 900 1:表示900 秒內如果至少有 1 個 key 的值變化,則儲存
save 300 10:表示300 秒內如果至少有 10 個 key 的值變化,則儲存
save 60 10000:表示60 秒內如果至少有 10000 個 key 的值變化,則儲存
那麼伺服器狀態中的saveparam 陣列將會是如下的樣子:
2.、dirty 計數器和lastsave 屬性
dirty 計數器記錄距離上一次成功執行 save 命令或者 bgsave 命令之後,Redis伺服器進行了多少次修改(包括寫入、刪除、更新等操作)。
lastsave 屬性是一個時間戳,記錄上一次成功執行 save 命令或者 bgsave 命令的時間。
通過這兩個命令,當伺服器成功執行一次修改操作,那麼dirty 計數器就會加 1,而lastsave 屬性記錄上一次執行save或bgsave的時間,Redis 伺服器還有一個週期性操作函式 severCron ,
預設每隔 100 毫秒(100毫秒檢查一次)就會執行一次,該函式會遍歷並檢查 saveparams 陣列中的所有儲存條件,只要有一個條件被滿足,那麼就會執行 bgsave 命令。
執行完成之後,dirty 計數器更新為 0 ,lastsave 也更新為執行命令的完成時間