Redis-持久化

来源:http://www.cnblogs.com/houziwty/archive/2016/02/02/5178250.html
-Advertisement-
Play Games

Redis 持久化 Redis 提供了不同持久化範圍的選項: RDB 持久化以指定的時間間隔執行數據集的即時點(point-in-time)快照。 AOF 持久化在服務端記錄每次收到的寫操作,在伺服器啟動時會重放,以重建原始數據集。命令使用和 Redis 協議一樣的格式以追加的方式來記錄。當文件太大


Redis 持久化

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

  • RDB 持久化以指定的時間間隔執行數據集的即時點(point-in-time)快照。
  • AOF 持久化在服務端記錄每次收到的寫操作,在伺服器啟動時會重放,以重建原始數據集。命令使用和 Redis 協議一樣的格式以追加的方式來記錄。當文件太大時 Redis 會在後臺重寫日誌。
  • 如果你願意,你可以完全禁止持久化,如果你只是希望你的數據在伺服器運行期間才存在的話。
  • 可以在同一個實例上同時支持 AOF 和 RDB。註意,在這種情況下,當 Redis 重啟時,AOF 文件會被用於重建原始數據集,因為它被保證是最完整的數據。

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

RDB 優點

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

RDB 缺點

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

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

AOF 優點

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

AOF 缺點

  • 對同樣的數據集,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)我們還沒有收到一份用戶在真實世界中檢測到崩潰的報告。

該選誰

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

    如果你很關註你的數據,但是仍然可以接受災難時有幾分鐘的數據丟失,你可以只單獨使用 RDB。

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

快照

     預設情況下,Redis 保存數據集快照到磁碟,名為 dump.rdb 的二進位文件。你可以設置讓 Redis 在 N 秒內至少有 M 次數據集改動時保存數據集,或者你也可以手動調用 SAVE 或者 BGSAVE 命令。

     例如,這個配置會讓 Redis 在每個 60 秒內至少有 1000 次鍵改動時自動轉儲數據集到磁碟:

save 60 1000

    這種策略被稱為快照。

如何工作

   每當 Redis 需要轉儲數據集到磁碟時,會發生:

  • Redis 調用 fork()。於是我們有了父子兩個進程。
  • 子進程開始將數據集寫入一個臨時 RDB 文件。
  • 當子進程完成了新 RDB 文件,替換掉舊文件。

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

只追加文件

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

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

   你可以在你的配置文件中開啟 AOF:

   

appendonly yes

從現在開始,每次 Redis 收到修改數據集的命令,將會被追加到 AOF 中。當你重啟 Redis 的時候,就會重放(re-play)AOF 文件來重建狀態。

日誌重寫

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

   於是 Redis 支持一個有趣的特性:在後臺重建 AOF 而不影響服務客戶端。每當你發送 BGREWRITEAOF 時,Redis 將會寫入一個新的 AOF 文件,包含重建當前記憶體中數據集所需的最短命令序列。如果你使用的是 Redis 2.2 的 AOF,你需要不時的運行 BGREWRITEAOF 命令。Redis 2.4 可以自動觸發日誌重寫(查看 Redis 2.4 中的示例配置文件以獲得更多信息)。

AOF 持久性如何

   你可以配置多久 Redis 會 fsync 數據到磁碟一次。有三個選項:

  • 每次一個新命令追加到 AOF 文件中時執行 fsync。非常非常慢,但是非常安全。
  • 每秒執行 fsync。夠快(2.4 版本中差不多和快照一樣快),但是當災難來臨時會丟失 1 秒的數據。
  • 從不執行 fsync,直接將你的數據交到操作系統手裡。更快,但是更不安全。

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

AOF 損壞了怎麼辦

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

  • 創建 AOF 的一個拷貝用於備份。
  • 使用 Redis 自帶的 redis-check-aof 工具來修複原文件:
  • $ redis-check-aof --fix
  • 使用 diff -u 來檢查兩個文件有什麼不同。用修複好的文件來重啟伺服器。

如何工作

日誌重寫採用了和快照一樣的寫時複製機制。下麵是過程:

  • Redis 調用 fork()。於是我們有了父子兩個進程。
  • 子進程開始向一個臨時文件中寫 AOF。
  • 父進程在一個記憶體緩衝區中積累新的變更(同時將新的變更寫入舊的 AOF 文件,所以即使重寫失敗我們也安全)。
  • 當子進程完成重寫文件,父進程收到一個信號,追加記憶體緩衝區到子進程創建的文件末尾。
  • 搞定!現在 Redis 自動重命名舊文件為新的,然後開始追加新數據到新文件。

如何從 RDB 切換到 AOF

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

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

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

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

   重要:記得編輯你的 redis.conf 文件來開啟 AOF,否則當你重啟伺服器時,你的配置修改將會丟失,伺服器又會使用舊的配置。

AOF 和 RDB 的相互作用

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

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

   Redis 在同時開啟 AOF 和 RDB 的情況下重啟,會使用 AOF 文件來重建原始數據集,因為通常 AOF 文件是保存數據最完整的。

備份數據

   一定要備份你的資料庫。磁碟損壞,雲中實例丟失,等等:沒有備份意味著數據丟失的巨大風險。

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

  這意味著,在伺服器運行時拷貝 RDB 文件是完全安全的。以下是我們的建議:

  • 創建一個定時任務(cron job),每隔一個小時創建一個 RDB 快照到一個目錄,每天的快照放在另外一個目錄。
  • 每次定時腳本運行時,務必使用 find 命令來刪除舊的快照:例如,你可以保存最近 48 小時內的每小時快照,一到兩個月的內的每天快照。註意命名快照時加上日期時間信息。
  • 至少每天一次將你的 RDB 快照傳輸到你的數據中心之外,或者至少傳輸到運行你的 Redis 實例的物理機之外。

災難恢復

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

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

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

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

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • iPhone中GPS定位如何使用 關鍵詞 1.info.plist配置授權描述 2.引入庫 3.CLLocationManager的使用 info.plist配置 在info.plist中根據情況加入以下兩個string類型配置項,並填寫描述 1.NSLocationAlwaysUsageDescr
  • 緣由: 平時工作,因為懶於動筆的原因,也沒註重技術和經驗的積累,導致之前曾經研究過的問題現在又忘記了,所以要慢慢註重積累,那麼就從寫作開始,談談對工作中碰到的問題進行整理和歸納。 我們都知道,在Android中,想處理事件傳遞,可以用Handler+MessageQueue+Message+Loop
  • STPopup 為 iPhone 和 iPad提供了 STPopupController UINavigationController 彈出的風格。 特性: Extend your view controller from UIViewController, build it in your fam
  • 筆記,listview視圖總結 1 public class HomeEduMoreAdapter extends BaseAdapter { 2 3 private final String TAG = "HomeEduMoreAdapter"; 4 5 private static final
  • 1 package com.gzcivil.utils; 2 3 /** 4 * 同StringBuffer 5 * 6 * @author Dragon 7 * @time 2013-3-1 8 */ 9 public class StrBuffer { 10 private StringBuff
  • 本文內容 創建 MySQL 用戶和組 解壓 MySQL 源代碼包 生成配置安裝文件 編譯和安裝 MySQL 配置文件 創建 MySQL 授權表 授權 啟動 MySQL 驗證安裝 設置訪問許可權 MySQL 開機自動啟動 最近做項目,出了一個事:之前我是用 Oracle 的,如果在 Windows 環境
  • CREATE OR REPLACE PACKAGE BODY BASE_INFO AS PROCEDURE insert_lapc(lapc In lapc_array) AS v_max number; v_result number; v_status number; BEGIN delete
  • a.安裝 本人下載的是windows版本的3.2.1mongo,路徑為https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.2.1-signed.msi 或者直接去官網也可以http://www.mongodb.or
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...