天天看點

Redis持久化-RDB與AOF

  Redis持久化(Persistence)  

    Redis提供了不同持久化範圍的選項: 

  • RDB持久化以指定的時間間隔執行資料集的即時點(point-in-time)快照。
  • AOF持久化在服務端記錄每次收到的寫操作,在伺服器啟動時會重放,以重建原始資料集。指令使用和Redis協定一樣的格式以追加的方式來記錄。當檔案太大時Redis會在背景重寫日志。
  • 如果你願意,你可以完全禁止持久化,如果你隻是希望你的資料在伺服器運作期間才存在的話。
  • 可以在同一個執行個體上同時支援AOF和RDB。注意,在這種情況下,當Redis重新開機時,AOF檔案會被用于重建原始資料集,因為它被保證是最完整的資料。

    了解RDB和AOF持久化之間的各自優劣(trade-offs)是一件非常重要的事情。讓我們先從RDB開始: 

     RDB優點(RDB advantages)  

  • RDB是一種表示某個即時點的Redis資料的緊湊檔案。RDB檔案适合用于備份。例如,你可能想要每小時歸檔最近24小時的RDB檔案,每天儲存近30天的RDB快照。這允許你很容易的恢複不同版本的資料集以容災。
  • RDB非常适合于災難恢複,作為一個緊湊的單一檔案,可以被傳輸到遠端的資料中心,或者是Amazon S3(可能得加密)。
  • RDB最大化了Redis的性能,因為Redis父程序持久化時唯一需要做的是啟動(fork)一個子程序,由子程序完成所有剩餘工作。父程序執行個體不需要執行像磁盤IO這樣的操作。
  • RDB在重新開機儲存了大資料集的執行個體時比AOF要快。

     RDB缺點(RDB disadvantages)  

    當你需要在Redis停止工作(例如停電)時最小化資料丢失,RDB可能不太好。你可以配置不同的儲存點(save point)來儲存RDB檔案(例如,至少5分鐘和對資料集100次寫之後,但是你可以有多個儲存點)。然而,你通常每隔5分鐘或更久建立一個RDB快照,是以一旦Redis因為任何原因沒有正确關閉而停止工作,你就得做好最近幾分鐘資料丢失的準備了。 

    RDB需要經常調用fork()子程序來持久化到磁盤。如果資料集很大的話,fork()比較耗時,結果就是,當資料集非常大并且CPU性能不夠強大的話,Redis會停止服務用戶端幾毫秒甚至一秒。AOF也需要fork(),但是你可以調整多久頻率重寫日志而不會有損(trade-off)持久性(durability)。 

     AOF優點(AOF advantages)  

  • 使用AOF Redis會更具有可持久性(durable):你可以有很多不同的fsync政策:沒有fsync,每秒fsync,每次請求時fsync。使用預設的每秒fsync政策,寫性能也仍然很不錯(fsync是由背景線程完成的,主線程繼續努力地執行寫請求),即便你也就僅僅隻損失一秒鐘的寫資料。
  • AOF日志是一個追加檔案,是以不需要定位,在斷電時也沒有損壞問題。即使由于某種原因檔案末尾是一個寫到一半的指令(磁盤滿或者其他原因),redis-check-aof工具也可以很輕易的修複。
  • 當AOF檔案變得很大時,Redis會自動在背景進行重寫。重寫是絕對安全的,因為Redis繼續往舊的檔案中追加,使用建立目前資料集所需的最小操作集合來建立一個全新的檔案,一旦第二個檔案建立完畢,Redis就會切換這兩個檔案,并開始往新檔案追加。
  • AOF檔案裡面包含一個接一個的操作,以易于了解和解析的格式存儲。你也可以輕易的導出一個AOF檔案。例如,即使你不小心錯誤地使用FLUSHALL指令清空一切,如果此時并沒有執行重寫,你仍然可以儲存你的資料集,你隻要停止伺服器,删除最後一條指令,然後重新開機Redis就可以。

     AOF缺點(AOF disadvantages)  

  • 對同樣的資料集,AOF檔案通常要大于等價的RDB檔案。
  • AOF可能比RDB慢,這取決于準确的fsync政策。通常fsync設定為每秒一次的話性能仍然很高,如果關閉fsync,即使在很高的負載下也和RDB一樣的快。不過,即使在很大的寫負載情況下,RDB還是能提供能好的最大延遲保證。
  • 在過去,我們經曆了一些針對特殊指令(例如,像BRPOPLPUSH這樣的阻塞指令)的罕見bug,導緻在資料加載時無法恢複到儲存時的樣子。這些bug很罕見,我們也在測試套件中進行了測試,自動随機創造複雜的資料集,然後加載它們以檢查一切是否正常,但是,這類bug幾乎不可能出現在RDB持久化中。為了說得更清楚一點:Redis AOF是通過遞增地更新一個已經存在的狀态,像MySQL或者MongoDB一樣,而RDB快照是一次又一次地從頭開始創造一切,概念上更健壯。但是,1)要注意Redis每次重寫AOF時都是以目前資料集中的真實資料從頭開始,相對于一直追加的AOF檔案(或者一次重寫讀取老的AOF檔案而不是讀記憶體中的資料)對bug的免疫力更強。2)我們還沒有收到一份使用者在真實世界中檢測到崩潰的報告。

     我們該選誰(what)  

    通常來說,你應該同時使用這兩種持久化方法,以達到和PostgreSQL提供的一樣的資料安全程度。 

    如果你很關注你的資料,但是仍然可以接受災難時有幾分鐘的資料丢失,你可以隻單獨使用RDB。 

    有很多使用者單獨使用AOF,但是我們并不鼓勵這樣,因為時常進行RDB快照非常友善于資料庫備份,啟動速度也較之快,還避免了AOF引擎的bug。 

    注意:基于這些原因,将來我們可能會統一AOF和RDB為一種單一的持久化模型(長遠計劃)。 

    下面的部分将介紹兩種持久化模型等多的細節。 

     快照(Snapshotting)  

    預設情況下,Redis儲存資料集快照到磁盤,名為dump.rdb的二進制檔案。你可以設定讓Redis在N秒内至少有M次資料集改動時儲存資料集,或者你也可以手動調用SAVE或者BGSAVE指令。 

    例如,這個配置會讓Redis在每個60秒内至少有1000次鍵改動時自動轉儲資料集到磁盤: 

Java代碼  

Redis持久化-RDB與AOF
  1. save 60 1000  

    這種政策被稱為快照。 

     如何工作(How works)  

    每當Redis需要轉儲資料集到磁盤時,會發生: 

  • Redis調用fork()。于是我們有了父子兩個程序。
  • 子程序開始将資料集寫入一個臨時RDB檔案。
  • 當子程序完成了新RDB檔案,替換掉舊檔案。

    這個方法可以讓Redis獲益于寫時複制(copy-on-write)機制。 

     隻追加檔案(Append-only file)  

    快照并不是非常具有可持久性(durable)。如果你運作Redis的電腦停機了,電源線斷了,或者你不小心kill -9掉你的執行個體,最近寫入Redis的資料将會丢失。盡管這個對一些應用程式來說不是什麼大事,但是也有一些需要完全可持久性(durability)的場景,在這些場景下可能就不合适了。 

    隻追加檔案是一個替代方案,是Redis的完全可持久性政策。在1.1版本中就可用了。 

    你可以在你的配置檔案中開啟AOF: 

Java代碼  

Redis持久化-RDB與AOF
  1. appendonly yes  

    從現在開始,每次Redis收到修改資料集的指令,将會被追加到AOF中。當你重新開機Redis的時候,就會重放(re-play)AOF檔案來重建狀态。 

     日志重寫(Log rewriting)  

    你可以猜得到,寫操作不斷執行的時候AOF檔案會越來越大。例如,如果你增加一個計數器100次,你的資料集裡隻會有一個鍵存儲這最終值,但是卻有100條記錄在AOF中。其中99條記錄在重建目前狀态時是不需要的。 

    于是Redis支援一個有趣的特性:在背景重建AOF而不影響服務用戶端。每當你發送BGREWRITEAOF時,Redis将會寫入一個新的AOF檔案,包含重建目前記憶體中資料集所需的最短指令序列。如果你使用的是Redis 2.2的AOF,你需要不時的運作BGREWRITEAOF指令。Redis 2.4可以自動觸發日志重寫(檢視Redis 2.4中的示例配置檔案以獲得更多資訊)。 

     AOF持久性如何(How durable)  

    你可以配置多久Redis會fsync資料到磁盤一次。有三個選項: 

  • 每次一個新指令追加到AOF檔案中時執行fsync。非常非常慢,但是非常安全。
  • 每秒執行fsync。夠快(2.4版本中差不多和快照一樣快),但是當災難來臨時會丢失1秒的資料。
  • 從不執行fsync,直接将你的資料交到作業系統手裡。更快,但是更不安全。

    建議的(也是預設的)政策是每秒執行一次fsync。既快,也相當安全。一直執行的政策在實踐中非常慢(盡管在Redis 2.0中有所改進),因為沒法讓fsync這個操作本身更快。 

     AOF損壞了怎麼辦(corrupted)  

    有可能在寫AOF檔案時伺服器崩潰(crash),檔案損壞後Redis就無法裝載了。如果這個發生的話,你可以使用下面的步驟來解決這個問題: 

  • 建立AOF的一個拷貝用于備份。
  • 使用Redis自帶的redis-check-aof工具來修複原檔案:
  • $ redis-check-aof --fix
  • 使用diff -u來檢查兩個檔案有什麼不同。
  • 用修複好的檔案來重新開機伺服器。

     如何工作(How works)  

    日志重寫采用了和快照一樣的寫時複制機制。下面是過程: 

  • Redis調用fork()。于是我們有了父子兩個程序。
  • 子程序開始向一個臨時檔案中寫AOF。
  • 父程序在一個記憶體緩沖區中積累新的變更(同時将新的變更寫入舊的AOF檔案,是以即使重寫失敗我們也安全)。
  • 當子程序完成重寫檔案,父程序收到一個信号,追加記憶體緩沖區到子程序建立的檔案末尾。
  • 搞定!現在Redis自動重命名舊檔案為新的,然後開始追加新資料到新檔案。

     如何從RDB切換到AOF(How switch)  

    在Redis 2.2及以上版本中非常簡單,也不需要重新開機。 

  • 備份你最新的dump.rdb檔案。
  • 把備份檔案放到一個安全的地方。
  • 發送以下兩個指令:
  • redis-cli config set appendonly yes
  • redis-cli config set save ""
  • 確定你的資料庫含有其包含的相同的鍵的數量。
  • 確定寫被正确的追加到AOF檔案。

    第一個CONFIG指令開啟AOF。Redis會阻塞以生成初始轉儲檔案,然後打開檔案準備寫,開始追加寫操作。 

    第二個CONFIG指令用于關閉快照持久化。這一步是可選的,如果你想同時開啟這兩種持久化方法。 

    重要:記得編輯你的redis.conf檔案來開啟AOF,否則當你重新開機伺服器時,你的配置修改将會丢失,伺服器又會使用舊的配置。 

    此處省略一萬字。。。。。。原文此處介紹2.0老版本怎麼操作。 

     AOF和RDB的互相作用(Interactions)  

    Redis 2.4及以後的版本中,不允許在RDB快照操作運作過程中觸發AOF重寫,也不允許在AOF重寫運作過程中運作BGSAVE。這防止了兩個Redis背景程序同時對磁盤進行繁重的IO操作。 

    當在快照運作的過程中,使用者使用BGREWRITEAOF顯式請求日志重寫操作的話,伺服器會答複一個OK狀态碼,告訴使用者這個操作已經被安排排程,等到快照完成時開始重寫。 

    Redis在同時開啟AOF和RDB的情況下重新開機,會使用AOF檔案來重建原始資料集,因為通常AOF檔案是儲存資料最完整的。 

     備份資料(Backing up)  

    開始這一部分之前,請務必牢記:一定要備份你的資料庫。磁盤損壞,雲中執行個體丢失,等等:沒有備份意味着資料丢失的巨大風險。 

    Redis對資料備份非常友好,因為你可以在資料庫運作時拷貝RDB檔案:RDB檔案一旦生成就不會被修改,檔案生成到一個臨時檔案中,當新的快照完成後,将自動使用rename(2)原子性的修改檔案名為目标檔案。 

    這意味着,在伺服器運作時拷貝RDB檔案是完全安全的。以下是我們的建議: 

  • 建立一個定時任務(cron job),每隔一個小時建立一個RDB快照到一個目錄,每天的快照放在另外一個目錄。
  • 每次定時腳本運作時,務必使用find指令來删除舊的快照:例如,你可以儲存最近48小時内的每小時快照,一到兩個月的内的每天快照。注意命名快照時加上日期時間資訊。
  • 至少每天一次将你的RDB快照傳輸到你的資料中心之外,或者至少傳輸到運作你的Redis執行個體的實體機之外。

     災難恢複(Disaster recovery)  

    在Redis中災難恢複基本上就是指備份,以及将這些備份傳輸到外部的多個資料中心。這樣即使一些災難性的事件影響到運作Redis和生成快照的主資料中心,資料也是安全的。 

    由于許多Redis使用者都是啟動階段的屌絲,沒有太多錢花,我們會介紹一些最有意思的災難恢複技術,而不用太多的花銷。 

  • Amazon S3和一些類似的服務是幫助你災難恢複系統的一個好辦法。隻需要将你的每日或每小時的RDB快照以加密的方式傳輸到S3.你可以使用gpg -c來加密你的資料(以對稱加密模式)。確定将你的密碼儲存在不同的安全地方(例如給一份到你的組織中的最重要的人)。推薦使用多個存儲服務來改進資料安全。
  • 使用SCP(SSH的組成部分)來傳輸你的快照到遠端伺服器。這是一種相當簡單和安全的方式:在遠離你的位置搞一個小的VPS,安裝ssh,生成一個無密碼的ssh用戶端key,并将其添加到你的VPS上的authorized_keys檔案中。你就可以自動的傳輸備份檔案了。為了達到好的效果,最好是至少從不同的提供商那搞兩個VPS。

    要知道這種系統如果沒有正确的處理會很容易失敗。至少一定要確定傳輸完成後驗證檔案的大小(要比對你拷貝的檔案),如果你使用VPS的話,可以使用SHA1摘要。 

    你還需要一個某種獨立的告警系統,在某些原因導緻的傳輸備份過程不正常時告警。 

繼續閱讀