RDB 持久化
一、生成RDB
cmd:SAVE --阻塞程式,執行完,才能有效接收客戶端命令。
cmd: BGSAVE --非阻塞,開啟子程式儲存。
客戶端如果傳送SAVE和BGSAVE命令直接拒絕。
BGWRITEAOF命令再BGSAVE執行完才能執行。
二、載入RDB
伺服器啟動時自動執行,檢測到RDB檔案就會自動載入。
如果開啟AOF,優先使用執行AOF。
AOF關閉的情況下,才會執行RDB。
三、自動間隔性儲存
save設定:一定條件後執行BGSAVE命令進行儲存
預設設定:
save 900 1 //900秒內,進行一次修改,觸發儲存BGSAVE
save 300 1 //300秒內,10次修改,觸發儲存BGSAVE
save 60 10000 //60秒內,1w次修改,觸發儲存BGSAVE
struct saveparam { time_t seconds; //秒數 int changes;//變化次數 };
還有兩個引數:
dirty --上次資料庫觸發儲存命令修改數
lastsave -- 最後一次執行save時間
PORT_LONGLONG dirty; /* Changes to DB from the last save */
time_t lastsave; /* Unix time of last successful save */
還有一個定時器預設100毫秒來檢測是否滿足save條件的方法:serverCron
int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData)
四、RDB檔案結構
| REDIS | db_version | database | EOF | check_sum |
RDB檔案開頭是REDIS,來判定是否是RDB檔案。
db_version 版本號
databse 包含任意多個資料庫(鍵值對)
EOF RDB檔案結束標誌
check_sum 校驗長度
AOF 持久化
一、命令持久化,儲存redis 的寫命令
二、命令追加
redis 執行完寫命令,將命令按照一定協議格式追加到 aof_buf 緩衝區
sds aof_buf; /* AOF buffer, written before entering the event loop */
三、AOF檔案寫入與同步
resid 伺服器程式是一個事件迴圈
檔案事件:接受命令和輸出內容
時間事件:負責定時任務
檔案事件執行寫命令,這樣會追加命令到aof_buf 緩衝區,在這寫命令結束之前會呼叫flushAppendOnlyFile 函式判斷是否從緩衝區回寫到AOF檔案。
寫入策略有三個:
always: 將aof_buf 緩衝區所有內容寫入並同步到AOF檔案。
everysec(預設): 將緩衝區內容寫入,超過一秒鐘,並進行同步。
no: 將緩衝區的所有內容同步,但是不同步。
四、AOF 載入以及資料還原
1、建立一個偽客戶端
2、分析aof檔案 並解析一條命令
3、偽客戶端執行此命令
4、迴圈執行2和3
五、AOF重寫
AOF 儲存寫命令,體積會膨脹,恢復資料庫的時間也會變長。
新建檔案AOF ,去除冗餘命令,合併命令。達到縮減檔案目的。
六、AOF後臺重寫
處理命令請求會因為這個aof重寫造成阻塞。
另起一個子程式,進行aof重寫。但是會存在資料不一致的問題,子程式在處理重寫一條命令後,同時主程式依然在寫當操作物件的命令。造成資料不一致。
解決方案:開闢aof重寫快取區
命令會直接寫入aof快取區和aof重寫快取區,這樣可以讀取快取區命令進行處理。類似佇列,先寫入佇列進行待處理。
生成的寫命令-->aof緩衝區 -->寫入同步到aof檔案
生成的寫命令-->aof重寫緩衝區 --> 寫完 -->傳送訊號給父程式 --> aof重寫緩衝區寫入新aof檔案 -->原子覆蓋舊aof檔案
父程式處理命令,儲存aof,使用子程式,覆蓋重寫aof,達到效能最佳不阻塞,同時生成的新aof也是比較小。