咱們知道,redis的數據是保存在內存裏,而內存一斷電就沒了,因此爲了數據持久化,咱們得想辦法把內存中的數據持久化到硬盤或者另外一臺機子上。
先說本地持久化到硬盤,這就有兩種方式,一是快照(snapshotting),二是隻追加文件(append-only file AOF)redis
快照的核心原理就是把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 copybash
可能會丟失數據
save 60 1000,若是我在60秒內只更新了800條數據,而後系統崩潰了,那麼這800條數據就沒了
第二:
大數據量的時候,作RDB,redis服務會暫停近1分鐘(20g的物理內存,redis裏面有13g的數據)!這個就是redis持久化的時候的服務暫停現象(爲啥?建立子進程,子進程的工做不須要資源麼?)。
一種方式就是,我關閉自動快照的設置,就是不要寫save 10 1000這樣的命令,而是在系統不忙的時候發送bgsave,至少我能控制何時系統發生停頓麼。再或者我發送save,這個雖然會停頓,可是由於不用建立子進程有時候也比較快。
服務器
還有一種就是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 文件所保存的數據集更完整。
不論是aof仍是快照都是把記錄保存在本地,在真正的大的生產中,用戶通常會使用複製機制,就是把本機的數據給遠程的另外一臺redis服務器發送一份。
這個我們下一節介紹。架構