持久化
一、RDB
- 概念
RDB持久化能夠在指定的時間間隔內生成數據集的時間點內存快照
- 配置
一、save 60 10000
二、rdbcompression yes
三、dbfilename "dump_6379.rdb"
四、dir "/appdata/redis/savefile"(AOF同)
- 命令
save
經過主進程,形成阻塞,期間不能執行任何命令
bgsave
fork()子進程後臺進行
- 優勢
一、恢復速度快,但載入過程當中會令redis一直處於阻塞狀態,直到載入完成;
二、可壓縮保存;
三、可最大化Redis性能,父進程fork子進程完成保存操做。
- 缺點
一、數據非實時保存,易丟失部分數據;
二、數據集大時,fork()操做耗時且消耗cpu。
二、AOF
- 概念
AOF 持久化記錄服務器執行的全部寫操做命令(append-only file)
- 配置
一、appendfsync
一、always
二、everysec
三、no(由系統決定同步頻率)
二、appendonly yes
三、appendfilename "appendonly.aof"
四、auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
- 建立一個不帶網絡鏈接的僞客戶端,由於redis的命令只能在客戶端上下文中執行;
- 從AOF文件中分析並讀取一條寫命令;
- 使用僞客戶端執行被讀出的寫命令;
- 一直重複步驟2和步驟3,直到AOF文件的全部寫命令被處理完畢爲止。
-
aof重寫機制 redis
- AOF文件重寫並不須要對現有的AOF文件進行任何讀取、分析或者寫入操做,這個功能是經過讀取服務器當前數據庫狀態來實現的。首先從數據庫中讀取鍵如今的值,而後用一條命令去記錄鍵值對,代替以前記錄這個鍵值對的多條命令,這就是AOF重寫功能的實現原理;
- 同時,爲了解決重寫期間有數據寫入致使現有AOF和重寫後的AOF數據不一致的問題,Redis設置了一個AOF重寫緩衝區,Redis執行完一個命令後,它會同時將這個寫命令發送給AOF緩衝區和AOF重寫緩衝區。
- AOF重寫完成後,會向父進程發送一個信號,父進程將調用信號處理函數執行如下操做:
1)將AOF重寫緩衝區的全部內容寫入新AOF文件中;
2)對新的AOF文件更名,原子地覆蓋現有的AOF文件,完成兩個文件的替換;
3)整個過程,只有信號處理函數執行時纔會對Redis父進程形成阻塞。
- aof重寫命令
bgrewriteaof fork()子進程重寫aof文件
- 優勢
一、較爲實時,默認(everysec)至多丟失一秒數據
二、redis-check-aof --fix 可修復AOF文件
三、文件可讀性強
四、可進行安全的rewrite操做
- 缺點
一、體積較大
二、根據fsync策略,AOF可能會致使redis速度低於RDB
三、優先級
- 優先AOF載入內存,只有關閉AOF功能時纔會載入載入RDB文件恢復數據庫;
- BGSAVE和BGREWRITE不可同時進,BGSAVE時發起BGREWRITE,後者會阻塞,等待BGSAVE完成後再開始,BGREWRITE時發起BGSAVE,會被拒絕。
四、寫時複製(Copy-On-Write)
(1) fork()
fork會建立一個子進程,子進程的是父進程的副本。數據庫
(2) exec()
exec函數的做用就是裝載一個新的程序(可執行映像)覆蓋當前進程內存空間中的映像,從而執行不一樣的任務。如redis的子進程專門用於進行bgsave或bgrewrite操做。 安全
(3) Copy-On-Write技術實現原理:
fork()以後,kernel把父進程中全部的內存頁的權限都設爲read-only,而後子進程的地址空間指向父進程。當父子進程都只讀內存時,相安無事。當其中某個進程寫內存時,CPU硬件檢測到內存頁是read-only的,因而觸發頁異常中斷(page-fault),陷入kernel的一箇中斷例程。中斷例程中,kernel就會把觸發的異常的頁複製一份,因而父子進程各自持有獨立的一份。 服務器
(4) Copy-On-Write優缺點?
優勢:網絡
- COW技術可減小分配和複製大量資源時帶來的瞬間延時;
- COW技術可減小沒必要要的資源分配。好比fork進程時,並非全部的頁面都須要複製,父進程的代碼段和只讀數據段都不被容許修改,因此無需複製。
缺點: app
- 若是在fork()以後,父子進程都還須要繼續進行寫操做,那麼會產生大量的分頁錯誤(頁異常中斷page-fault),這樣就得不償失。
(5) Copy-On-Write在redis上的應用 ide
- Redis在持久化時,若是是採用BGSAVE命令或者BGREWRITEAOF的方式,那Redis會fork出一個子進程來讀取數據,從而寫到磁盤中。
- 整體來看,Redis仍是讀操做比較多。若是子進程存在期間,發生了大量的寫操做,那可能就會出現不少的分頁錯誤(頁異常中斷page-fault),這樣就得耗費很多性能在複製上。
- 在rehash階段上,寫操做是沒法避免的。根據 BGSAVE 命令或 BGREWRITEAOF 命令是否正在執行, 服務器執行擴展操做所需的負載因子並不相同, 這是由於在執行 BGSAVE命令或 BGREWRITEAOF 命令的過程當中, Redis 須要建立當前服務器進程的子進程, 而大多數操做系統都採用寫時複製(copy-on-write)技術來優化子進程的使用效率, 因此在子進程存在期間, 服務器會提升執行擴展操做所需的負載因子, 從而儘量地避免在子進程存在期間進行哈希表擴展操做, 這能夠避免沒必要要的內存寫入操做, 最大限度地節約內存。