Redis持久化(转载)
原文地址:http://www.jianshu.com/p/2f14bc570563?from=jiantop.com
?
數據持久化
Redis提供了將數據定期自動持久化至硬盤的能力,包括RDB和AOF兩種方案,兩種方案分別有其長處和短板,可以配合起來同時運行,確保數據的穩定性。
必須使用數據持久化嗎?
Redis的數據持久化機制是可以關閉的。如果你只把Redis作為緩存服務使用,Redis中存儲的所有數據都不是該數據的主體而僅僅是同步過來的備份,那么可以關閉Redis的數據持久化機制。
但通常來說,仍然建議至少開啟RDB方式的數據持久化,因為:
- RDB方式的持久化幾乎不損耗Redis本身的性能,在進行RDB持久化時,Redis主進程唯一需要做的事情就是fork出一個子進程,所有持久化工作都由子進程完成
- Redis無論因為什么原因crash掉之后,重啟時能夠自動恢復到上一次RDB快照中記錄的數據。這省去了手工從其他數據源(如DB)同步數據的過程,而且要比其他任何的數據恢復方式都要快
- 現在硬盤那么大,真的不缺那一點地方
RDB
采用RDB持久方式,Redis會定期保存數據快照至一個rbd文件中,并在啟動時自動加載rdb文件,恢復之前保存的數據。可以在配置文件中配置Redis進行快照保存的時機:
save [seconds] [changes]
意為在[seconds]秒內如果發生了[changes]次數據修改,則進行一次RDB快照保存,例如
save 60 100
會讓Redis每60秒檢查一次數據變更情況,如果發生了100次或以上的數據變更,則進行RDB快照保存。
可以配置多條save指令,讓Redis執行多級的快照保存策略。
Redis默認開啟RDB快照,默認的RDB策略如下:
save 900 1
save 300 10
save 60 10000
也可以通過BGSAVE命令手工觸發RDB快照保存。
RDB的優點:
- 對性能影響最小。如前文所述,Redis在保存RDB快照時會fork出子進程進行,幾乎不影響Redis處理客戶端請求的效率。(但是如果數據量比較大,那么會造成比較大的延遲)
- 每次快照會生成一個完整的數據快照文件,所以可以輔以其他手段保存多個時間點的快照(例如把每天0點的快照備份至其他存儲媒介中),作為非??煽康臑碾y恢復手段。
- 使用RDB文件進行數據恢復比使用AOF要快很多。
RDB的缺點:
- 快照是定期生成的,所以在Redis crash時或多或少會丟失一部分數據。
- 如果數據集非常大且CPU不夠強(比如單核CPU),Redis在fork子進程時可能會消耗相對較長的時間(長至1秒),影響這期間的客戶端請求。
AOF
采用AOF持久方式時,Redis會把每一個寫請求都記錄在一個日志文件里。在Redis重啟時,會把AOF文件中記錄的所有寫操作順序執行一遍,確保數據恢復到最新。
AOF默認是關閉的,如要開啟,進行如下配置:
appendonly yes
AOF提供了三種fsync配置,always/everysec/no,通過配置項[appendfsync]指定:
- appendfsync no:不進行fsync,將flush文件的時機交給OS決定,速度最快
- appendfsync always:每寫入一條日志就進行一次fsync操作,數據安全性最高,但速度最慢
- appendfsync everysec:折中的做法,交由后臺線程每秒fsync一次
aof?比快照方式有更好的持久化性,是由于在使用aof持久化方式時,redis會將每一個收到的寫命令都通過write函數追加到文件中(默認是appendonly.aof)。當redis重啟時會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。當然由于os會在內核中緩存?write做的修改,所以可能不是立即寫到磁盤上。這樣aof方式的持久化也還是有可能會丟失部分修改。
隨著AOF不斷地記錄寫操作日志,必定會出現一些無用的日志,例如某個時間點執行了命令SET key1 "abc",在之后某個時間點又執行了SET key1 "bcd",那么第一條命令很顯然是沒有用的。大量的無用日志會讓AOF文件過大,也會讓數據恢復的時間過長。
所以Redis提供了AOF rewrite功能,可以重寫AOF文件,只保留能夠把數據恢復到最新狀態的最小寫操作集(我理解的,比如同一個key,set多次,只最后一次的。)。
AOF rewrite可以通過BGREWRITEAOF命令觸發,也可以配置Redis定期自動進行:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上面兩行配置的含義是,Redis在每次AOF rewrite時,會記錄完成rewrite后的AOF日志大小,當AOF日志大小在該基礎上增長了100%后,自動進行AOF rewrite。同時如果增長的大小沒有達到64mb,則不會進行rewrite。
AOF的優點:
- 最安全,在啟用appendfsync always時,任何已寫入的數據都不會丟失,使用在啟用appendfsync everysec也至多只會丟失1秒的數據。
- AOF文件在發生斷電等問題時也不會損壞,即使出現了某條日志只寫入了一半的情況,也可以使用redis-check-aof工具輕松修復。
- AOF文件易讀,可修改,在進行了某些錯誤的數據清除操作后,只要AOF文件沒有rewrite,就可以把AOF文件備份出來,把錯誤的命令刪除,然后恢復數據。
AOF的缺點:
- AOF文件通常比RDB文件更大
- 性能消耗比RDB高
- 數據恢復速度比RDB慢
?
?
Redis實戰中說:
當redis中存儲的數據量只有幾個G的時候,使用快照來保存數據是沒有問題的。redis會創建子進程并將數據保存到硬盤里面,生成快照的時間很短,但是如果redis占用的內存越來越大,BGSAVE占用的時間會很長,導致系統長時間的停頓。所以最好的方式是,在凌晨發送SAVA來執行快照,然后其他時間用AOF來保證持久性。
?
?
?
下面介紹詳細的快照保存過程
1.redis調用fork,現在有了子進程和父進程。
2. 父進程繼續處理client請求,子進程負責將內存內容寫入到臨時文件。由于os的寫時復制機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時os會為父進程要修改的頁面創建副本(注:應該是把修改前的段創建副本給子進程),而不是寫共享的頁面。所以子進程的地址空間內的數 據是fork時刻整個數據庫的一個快照。
3.當子進程將快照寫入臨時文件完畢后,用臨時文件替換原來的快照文件,然后子進程退出。
client 也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主線程中保存快照的,由于redis是用一個主線程來處理所有 client的請求,這種方式會阻塞所有client請求。所以不推薦使用。另一點需要注意的是,每次快照持久化都是將內存數據完整寫入到磁盤一次,并不 是增量的只同步臟數據。如果數據量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。
?
?
個人理解:根據上面所說,之所以在內存大的時候fork出來的子進程會影響到父進程造成停頓,并不是父進程被掛起了,而是子進程大量操作IO和內存讀取,導致父進程運行緩慢。
?
轉載于:https://www.cnblogs.com/xiaolang8762400/p/7226285.html
總結
以上是生活随笔為你收集整理的Redis持久化(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到扒坟开棺是什么意思
- 下一篇: 关于json格式字符串解析并用mybat