本文轉自互聯網git
本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內容請到個人倉庫裏查看github
喜歡的話麻煩點下Star哈redis
文章首發於個人我的博客:數據庫
www.how2playlife.com緩存
本文是微信公衆號【Java技術江湖】的《探索Redis設計與實現》其中一篇,本文部份內容來源於網絡,爲了把本文主題講得清晰透徹,也整合了不少我認爲不錯的技術博客內容,引用其中了一些比較好的博客文章,若有侵權,請聯繫做者。安全
該系列博文會告訴你如何從入門到進階,Redis基本的使用方法,Redis的基本數據結構,以及一些進階的使用方法,同時也須要進一步瞭解Redis的底層數據結構,再接着,還會帶來Redis主從複製、集羣、分佈式鎖等方面的相關內容,以及做爲緩存的一些使用方法和注意事項,以便讓你更完整地瞭解整個Redis相關的技術體系,造成本身的知識框架。服務器
若是對本系列文章有什麼建議,或者是有什麼疑問的話,也能夠關注公衆號【Java技術江湖】聯繫做者,歡迎你參與本系列博文的創做和修訂。微信
咱們知道Redis是一款內存服務器,就算咱們對本身的服務器足夠的信任,不會出現任何軟件或者硬件的故障,但也會有可能出現忽然斷電等狀況,形成Redis服務器中的數據失效。所以,咱們須要向傳統的關係型數據庫同樣對數據進行備份,將Redis在內存中的數據持久化到硬盤等非易失性介質中,來保證數據的可靠性。網絡
將Redis內存服務器中的數據持久化到硬盤等介質中的一個好處就是,使得咱們的服務器在重啓以後還能夠重用之前的數據,或者是爲了防止系統出現故障而將數據備份到一個遠程的位置。
還有一些場景,例如:
對於一些須要進行大量計算而獲得的數據,放置在Redis服務器,咱們就有必要對其進行數據的持久化,若是須要對數據進行恢復的時候,咱們就不需進行從新的計算,只須要簡單的將這臺機器上的數據複製到另外一臺須要恢復的Redis服務器就能夠了。
Redis給咱們提供了兩種不一樣方式的持久化方法:快照(Snapshotting) 和 只追加文件(append-only-file)。
(1)名詞簡介
快照(RDB):就是咱們俗稱的備份,他能夠在按期內對數據進行備份,將Redis服務器中的數據持久化到硬盤中;
只追加文件(AOF):他會在執行寫命令的時候,將執行的寫命令複製到硬盤裏面,後期恢復的時候,只須要從新執行一下這個寫命令就能夠了。相似於咱們的MySQL數據庫在進行主從複製的時候,使用的是binlog
二進制文件,一樣的是執行一遍寫命令;
(2)快照持久化通用的配置:
save 60 1000 #60秒時間內有1000次寫入操做的時候執行快照的建立stop-writes-on-bgsave-error no #建立快照失敗的時候是否仍然繼續執行寫命令rdbcompression yes #是否對快照文件進行壓縮dbfilename dump.rdb #如何命名硬盤上的快照文件dir ./ #快照所保存的位置
(3)AOP持久化配置:
appendonly no #是否使用AOF持久化appendfsync everysec #多久執行一次將寫入內容同步到硬盤上no-appendfsync-on-rewrite no #對AOF進行壓縮的時候可否執行同步操做auto-aof-rewrite-percentage 100 #多久執行一次AOF壓縮auto-aof-rewrite-min-size 64mb #多久執行一次AOF壓縮dir ./ #AOF所保存的位置
須要注意的是:這兩種持久化的方式既能夠單獨的使用,也能夠同時使用,具體選擇哪一種方式須要根據具體的狀況進行選擇。
快照就是咱們所說的備份。用戶能夠將Redis內存中的數據在某一個時間點進行備份,在建立快照以後,用戶能夠對快照進行備份。一般狀況下,爲了防止單臺服務器出現故障形成全部數據的丟失,咱們還能夠將快照複製到其餘服務器,建立具備相同數據的數據副本,這樣的話,數據恢復的時候或者服務器重啓的時候就可使用這些快照信息進行數據的恢復,也能夠防止單臺服務器出現故障的時候形成數據的丟失。
可是,沒咱們還須要注意的是,建立快照的方式,並不能徹底保證咱們的數據不丟失,這個你們能夠很好的理解,由於快照的建立時定時的,並非每一次更新操做都會建立一個快照的。系統發生崩潰的時候,用戶將丟失最近一次生成快照以後更改的全部數據。所以,快照持久化的方式只適合於數據不常常修改或者丟失部分數據影響不大的場景。
1、建立快照的方式:
(1)客戶端經過向Redis發送BGSAVE
命令來建立快照。
使用BGSAVE的時候,Redis會調用fork來建立一個子進程,而後子進程負責將快照寫到硬盤中,而父進程則繼續處理命令請求。
使用場景:
若是用戶使用了save設置,例如:save 60 1000
,那麼從Redis最近一次建立快照以後開始計算,當「60秒以內有1000次寫入操做」這個條件知足的時候,Redis就會自動觸發BGSAVE命令。
若是用戶使用了多個save設置,那麼當任意一個save配置知足條件的時候,Redis都會觸發一次BGSAVE命令。
(2)客戶端經過向Redis發送SAVE
命令來建立快照。
接收到SAVE命令的Redis服務器在快照建立完畢以前將再也不響應任何其餘命令的請求。SAVE命令並不經常使用,咱們一般只在沒有足夠的內存去執行BGSAVE命令的時候纔會使用SAVE命令,或者即便等待持久化操做執行完畢也無所謂的狀況下,纔會使用這個命令;
使用場景:
當Redis經過SHUTDOWN命令接收到關閉服務器的請求時,或者接收到標準的TERM信號時,會執行一次SAVE命令,阻塞全部的客戶端,再也不執行客戶端發送的任何命令,而且在執行完SAVE命令以後關閉服務器。
2、使用快照持久化注意事項:
咱們在使用快照的方式來保存數據的時候,若是Redis服務器中的數據量比較小的話,例如只有幾個GB的時候。Redis會建立子進程並將數據保存到硬盤裏邊,生成快照所需的時間比讀取數據所須要的時間還要短。
可是,隨着數據的增大,Redis佔用的內存愈來愈大的時候,BGSAVE在建立子進程的時候消耗的時間也會愈來愈多,若是Redis服務器所剩下的內存很少的時候,這行BGSAVE命令會使得系統長時間地停頓,還有可能致使服務器沒法使用。
各虛擬機類別,建立子線程所耗時間:
所以,爲了防止Redis由於建立子進程的時候出現停頓,咱們能夠考慮關閉自動保存,轉而經過手動的方式發送BGSAVE或者SAVE來進行持久化,
手動的方式發送BGSAVE也會出現停頓的現象,可是咱們能夠控制發送該命令的時間來控制出現停頓的時候不影響具體的業務請求。
另外,值得注意的是,在使用SAVE命令的時候,雖然會一直阻塞Redis直到快照生成完畢,可是其不須要建立子進程,因此不會向BGSAVE同樣,由於建立子進程而致使Redis停頓。也正由於如此,SAVE建立快照的速度要比BGSAVE建立快照的速度更快一些。
建立快照的時候,咱們能夠在業務請求,比較少的時候,好比凌晨3、四點,經過手寫腳本的方式,定時執行。
AOF持久化會將被執行的寫命令寫到AOF文件的末尾,以此來記錄數據發生的變化。這樣,咱們在恢復數據的時候,只須要從頭至尾的執行一下AOF文件便可恢復數據。
1、打開AOF持久化選項
咱們能夠經過使用以下命令打開AOF:
appendonly yes
咱們,經過以下命令來配置AOF文件的同步頻率:
appendfsync everysec/always/no
2、appendfsync同步頻率的區別
appendfsync同步頻率的區別以下圖:
(1)always的方式當然能夠對沒一條數據進行很好的保存,可是這種同步策略須要對硬盤進行大量的寫操做,因此Redis處理命令的速度會受到硬盤性能的限制。
普通的硬盤每秒鐘只能處理大約200個寫命令,使用固態硬盤SSD每秒能夠處理幾萬個寫命令,可是每次只寫一個命令,這種只能怪不斷地寫入不多量的數據的作法有可能引起嚴重的寫入放大問題,這種狀況降低嚴重影響固態硬盤的使用壽命。
(2)everysec的方式,Redis以每秒一次的頻率大隊AOF文件進行同步。這樣的話既能夠兼顧數據安全也能夠兼顧寫入性能。
Redis以每秒同步一次AOF文件的性能和不使用任何持久化特性時的性能相差無幾,使用每秒更新一次 的方式,能夠保證,即便出現故障,丟失的數據也在一秒以內產生的數據。
(3)no的方式,Redis將不對AOF文件執行任何顯示的同步操做,而是由操做系統來決定應該什麼時候對AOF文件進行同步。
這個命令通常不會對Redis的性能形成多大的影響,可是當系統出現故障的時候使用這種選項的Redis服務器丟失不定數量的數據。
另外,當用戶的硬盤處理寫入操做的速度不夠快的話,那麼緩衝區被等待寫入硬盤的數據填滿時,Redis的寫入操做將被阻塞,並致使Redis處理命令請求的速度變慢,由於這個緣由,通常不推薦使用這個選項。
3、重寫/壓縮AOF文件
隨着數據量的增大,AOF的文件可能會很大,這樣在每次進行數據恢復的時候就會進行很長的時間,爲了解決日益增大的AOF文件,用戶能夠向Redis發送BGREWRITEAOF
命令,這個命令會經過移除AOF文件中的冗餘命令來重寫AOF文件,是AOF文件的體檢變得儘量的小。
BGREWRITEAOF的工做原理和BGSAVE的原理很像:Redis會建立一個子進程,而後由子進程負責對AOF文件的重寫操做。
由於AOF文件重寫的時候匯建立子進程,因此快照持久化由於建立子進程而致使的性能和內存佔用問題一樣會出如今AOF文件重寫的 時候。
4、觸發重寫/壓縮AOF文件條件設定
AOF經過設置auto-aof-rewrite-percentage
和 auto-aof-rewrite-min-size
選項來自動執行BGREWRITEAOF。
其具體含義,經過實例能夠看出,以下配置:
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
表示當前AOF的文件體積大於64MB,而且AOF文件的體積比上一次重寫以後的體積變大了至少一倍(100%)的時候,Redis將執行重寫BGREWRITEAOF命令。
若是AOF重寫執行的過於頻繁的話,能夠將auto-aof-rewrite-percentage
選項的值設置爲100以上,這種最偶發就可讓Redis在AOF文件的體積變得更大以後才執行重寫操做,不過,這也使得在進行數據恢復的時候執行的時間變得更加長一些。
不管使用哪一種方式進行持久化,咱們在進行恢復數據的時候,Redis提供了兩個命令行程序:
redis-check-aofredis-check-dump
他們能夠再系統發生故障的時候,檢查快照和AOF文件的狀態,並對有須要的狀況對文件進行修復。
若是用戶在運行redis-check-aof命令的時候,指定了--fix
參數,那麼程序將對AOF文件進行修復。
程序修復AOF文件的方法很簡單:他會掃描給定的AOF文件,尋找不正確或者不完整的命令,當發現第一個出現錯誤命令的時候,程序會刪除出錯命令以及出錯命令以後的全部命令,只保留那些位於出錯命令以前的正確命令。大部分狀況,被刪除的都是AOF文件末尾的不完整的寫命令。
上述,一塊兒學習了兩種支持持久化的方式,一方面咱們須要經過快照或者AOF的方式對數據進行持久化,另外一方面,咱們還須要將持久化所獲得的文件進行備份,備份到不一樣的服務器上,這樣才能夠儘量的減小數據丟失的損失。
參考文章:
一、Redis in Action - [美] Josiah L.Carlsono