redis快照與AOF


我們知道,redis的數據是保存在內存里,而內存一斷電就沒了,所以為了數據持久化,我們得想辦法把內存中的數據持久化到硬盤或者另一台機子上。


先說本地持久化到硬盤,這就有兩種方式,一是快照(snapshotting),二是只追加文件(append-only file AOF)

快照

快照的核心原理就是把redis在某個時間內存內的所有數據都寫入硬盤,那么什么時候寫入呢?快照的配置都有哪些呢?
出現下面的情況redis會快照內存里的數據
1 用戶發送bgsave命令(此時redis會fork一個子進程,子進程負責生成硬盤文件,父進程負責繼續接受命令)
2 用戶發送save命令(和bgsave命令不同,發送save命令后,到系統創建快照完成之前系統不會再接收新的命令,換句話說save命令會阻塞后面的命令,而bgsave不會)
3 用戶在配置文件了配置了類似這樣的命令 
  save 60 1000
  這個的意思是說,自從上次快照成功算起,如果滿足"60秒內有1000次寫入"這個條件,系統就自動調用bgsave,如果配置文件里有多個save命令,只有滿足一個就調用bgsave命令
4 用戶發送shutdown,系統會先導員save命令阻塞客戶端,然后關閉服務器
5 當有主從架構時,從服務器向主服務器發送sync命令來執行復制操作時,只有主服務器當時沒有進行bgsave操作,那么主服務器就會執行bgsave操作。更多的關於主從復制的信息,見下文

快照的配置信息

save 60 1000           
stop-writes-on-bgsave-error no
rdbcompression yes
dbfilename dump.rdb
dir ./
第一個配置不用解釋了,第二個看英文就是失敗后是否暫停寫命令,第三個寫的時候是否壓縮,第五和第四合起來構成了數據文件的全地址


加入下午3:12分完成了一次快照,一切OK,在4:25開始進行第二次快照,持續了2分鍾,一直到4:27次成功生成快照文件。在這2分鍾內,系統又更新了35個鍵。如果在這2分鍾內系統發生了崩潰,那么我們就丟失了自3:12以后的所有數據。如果系統在剛完成快照且那35個鍵還沒有寫入硬盤時就崩潰了,那我們就丟失了35個鍵。

快照的優勢

快照的文件適合備份
我們建立下面的文件,讓他每天凌晨3點執行,就能獲得每天redis的版本了

[plain]  view plain  copy
 
  1. #! /bin/bash  
  2.    
  3. PATH=/usr/local/bin:$PATH  
  4. redis-cli SAVE  
  5.    
  6. date=$(date +"%Y%m%d")  
  7. cp /var/lib/redis/6379/dump.rdb /data01/cache_backup/$date.rdb  
  8.    
  9. echo "done!"  

快照的劣勢

可能會丟失數據
save 60 1000,如果我在60秒內只更新了800條數據,然后系統崩潰了,那么這800條數據就沒了
第二:
大數據量的時候,做RDB,redis服務會暫停近1分鍾(20g的物理內存,redis里面有13g的數據)!這個就是redis持久化的時候的服務暫停現象(為啥?創建子進程,子進程的工作不需要資源么?)。
一種方式就是,我關閉自動快照的設置,就是不要寫save 10 1000這樣的命令,而是在系統不忙的時候發送bgsave,至少我能控制什么時候系統發生停頓么。再或者我發送save,這個雖然會停頓,但是因為不用創建子進程有時候也比較快。

AOF

還有一種就是aof
這是什么呀?就是系統會把所有的redis數據進行的寫操作的命令記錄到硬盤上,這樣一來恢復的時候,再執行一次命令就OK了
它有下面幾個設置屬性
appendonly no    #是否開啟aof 
appendfsync everysec  
no-appendfsync-on-rewrite no
這個配置項是設置在rewrite的時候是否對新的寫操作進行fsync(將緩存中的命令寫入硬盤)。no表示進行fsync,yes表示不進行默認是設置為no
rewrite是將寫操作合並,比如set aa 1; set aa 2; 兩個操作應該寫成一個操作set aa 2;而什么時候進行rewrite呢?就是aof文件太大的時候
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
appendfsync有三種選擇分別是always,everysec,no
always就是每次有一個寫命令,就把命令存的硬盤文件里
everysec就是每秒寫入硬盤一次
no就是由操作系統來確認什么時候寫
我們一般都使用everysec,每秒把寫命令寫入到硬盤與不進行任何持久化操作在性能上沒有什么區別。
aof優勢在於:就算出問題了,最多丟失1秒內的更新數據
aof的劣勢:
aof文件的體積可能會很大(可能比快照文件還大),另一方面,系統重啟的時候回從aof里讀命令,如果aof文件太大,讀命令也就要還很久

怎么辦?系統可以重寫aof文件,盡量把文件體積縮小
不過重寫的操作也是系統fork一個進程做的,那么在快照里存在的內存占用與性能問題,也會存在。
no-appendfsync-on-rewrite
這個配置項是設置在rewrite的時候是否對新的寫操作進行fsync。no表示進行fsync,yes表示不進行
默認是設置為no
重寫的時候,get操作是沒有問題的,但是如果no-appendfsync-on-rewrite為no,那么寫數據就會出現延遲。
我們把no-appendfsync-on-rewrite改成yes,寫就沒有延遲了

也就是說,aof也是由問題的
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上面這個兩個命令的意思是當現在的aof文件大於64mb,且現在的文件比上一次重寫后的文件體積增加了至少100%,那么就立刻重寫aof文件。



RDB 和 AOF ,我應該用哪一個?
一般來說,如果想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。如果你非常關心你的數據,但仍然可以承受數分鍾以內的數據丟失, 那么你可以只使用 RDB 持久化。有很多用戶都只使用 AOF 持久化, 但我們並不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快, 除此之外, 使用 RDB 還可以避免之前提到的 AOF 程序的 bug 。因為以上提到的種種原因, 未來我們可能會將 AOF 和 RDB 整合成單個持久化模型。 (這是一個長期計划。)
(上面兩段,復制自:https://my.oschina.net/davehe/blog/174662)

同時使用快照與aof時,當 Redis 重啟時, 它會優先使用 AOF 文件來還原數據集, 因為 AOF 文件保存的數據集通常比 RDB 文件所保存的數據集更完整。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM