RDB是Redis持久化數據的一種方式,是執行時間點的Redis內存快照,redis數據還原時加載rdb文件,Redis的主從數據同步也是基於RDB實現的。redis
RDB流程:安全
1)執行bgsave命令,Redis父進程判斷當前是否存在正在執行的子進程,如RDB/AOF子進程,若是存在bgsave命令直接返回。服務器
2)父進程執行fork操做建立子進程,fork操做過程當中父進程會阻塞,經過info stats命令查看latest_fork_usec選項,能夠獲取最近一個fork操做的耗時,單位爲微秒。app
3)父進程fork完成後,bgsave命令返回「Background saving started」信息並再也不阻塞父進程,能夠繼續響應其餘命令。性能
4)子進程建立RDB文件,根據父進程內存生成臨時快照文件,完成後對原有文件進行原子替換。執行lastsave命令能夠獲取最後一次生成RDB的時間,對應info統計的rdb_last_save_time選項。spa
5)進程發送信號給父進程表示完成,父進程更新統計信息,具體見info Persistence下的rdb_*相關選項。操作系統
AOF是Redis持久化數據的另外一種方式,這種方式以日誌形式記錄每一條操做,當redis恢復數據時,還原全部操做。線程
AOF流程:日誌
1)全部的寫入命令會追加到aof_buf中。blog
2)AOF緩衝區根據對應的策略向硬盤作同步操做。
3)隨着AOF文件愈來愈大,須要按期對AOF文件進行重寫,達到壓縮的目的。
4)當Redis服務器重啓時,能夠加載AOF文件進行數據恢復。
AOF緩衝區同步文件策略(配置appendfsync參數)說明:
always:命令寫入aof_buf後調用系統fsync操做同步到AOF文件,fsync完成後線程返回
everysec:命令寫入aof_buf後調用系統write操做,write完成後線程返回。fsync同步文件操做由專門線程每秒調用一次
no:命令寫入aof_buf後調用系統write操做,不對AOF文件作fsync同步,同步硬盤操做由操做系統負責,一般同步週期最長30s
配置爲always時,每次寫入都要同步AOF文件,在通常的SATA硬盤上,Redis只能支持大約幾百TPS寫入,顯然跟Redis高性能特性背道而馳,不建議配置。
配置爲no,因爲操做系統每次同步AOF文件的週期不可控,並且會加大每次同步硬盤的數據量,雖然提高了性能,但數據安全性沒法保證。
配置爲everysec,是建議的同步策略,也是默認配置,作到兼顧性能和數據安全性。理論上只有在系統忽然宕機的狀況下丟失1秒的數據。
(策略選擇根據業務不一樣進行選擇)
系統調用write和fsync說明:
write操做會觸發延遲寫(delayed write)機制,Linux在內核提供頁緩衝區用來提升硬盤IO性能,write操做在寫入系統緩衝區後直接返回,同步硬盤操做依賴於系統調度機制,例如:
緩衝區頁空間寫滿或達到特定時間週期。同步文件以前,若是此時系統故障宕機,緩衝區內數據將丟失。
fsync針對單個文件操做(好比AOF文件),作強制硬盤同步,fsync將阻塞直到寫入硬盤完成後返回,保證了數據持久化。
子進程經過fork操做產生,佔用內存大小等同於父進程,理論上須要兩倍的內存來完成持久化操做,但Linux有寫時複製機制(copy-on-write)。父子進程會共享相同的物理內存頁,當父進程處理寫請求時會把要修改的頁建立副本,而子進程在fork操做過程當中共享整個父進程內存快照。避免在大量寫入時作子進程重寫操做,這樣將致使父進程維護大量頁副本,形成內存消耗。
Linux kernel在2.6.38內核增長了Transparent Huge Pages(THP),支持huge page(2MB)的頁分配,默認開啓。當開啓時能夠下降fork建立子進程的速度,但執行fork以後,若是開啓THP,複製頁單位從原來4KB變爲2MB,會大幅增長重寫期間父進程內存消耗。建議設置「sudo echonever>/sys/kernel/mm/transparent_hugepage/enabled」關閉THP。
RDB和AOF對比:
RDB文件緊湊小巧,RDB文件生成又子進程完成,不會阻塞主進程,而且能夠利用多核CPU資源,數據的恢復速度也比AOF快,可是RDB方式容易丟失數據,有些公司爲了充分利用CPU資源,將Redis進程與cpu核心進行綁定,進行RDB時子進程與父進程會發生資源競爭,影響服務吞吐。
AOF更加安全,能夠將數據更加及時的同步到文件中,可是AOF須要較多的磁盤IO開支,AOF文件尺寸較大,文件內容恢復數度相對較慢。
下一篇會介紹主從複製流程