解密Redis的持久化和主從複製機制

各位小夥伴,上次講了《深刻淺出Redis》和《Redis安裝和實際應用》本篇文章將爲你們解密redis的持久化和主從複製機制。php

Redis持久化

Redis 提供了多種不一樣級別的持久化方式:html

  • RDB 持久化能夠在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)。
  • AOF 持久化記錄服務器執行的全部寫操做命令,並在服務器啓動時,經過從新執行這些命令來還原數據集。 AOF 文件中的命令所有以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 Redis 還能夠在後臺對 AOF 文件進行重寫(rewrite),使得 AOF 文件的體積不會超出保存數據集狀態所需的實際大小。
  • Redis 還能夠同時使用 AOF 持久化和 RDB 持久化。 在這種狀況下, 當 Redis 重啓時, 它會優先使用 AOF 文件來還原數據集, 由於 AOF 文件保存的數據集一般比 RDB 文件所保存的數據集更完整。
  • 你甚至能夠關閉持久化功能,讓數據只在服務器運行時存在。

RDB(Redis DataBase)

Rdb:在指定的時間間隔內將內存中的數據集快照寫入磁盤,也就是行話講的 snapshot 快照,它恢復時就是將快照文件直接讀到內存裏。
Redis 會單獨的建立(fork) 一個子進程來進行持久化,會先將數據寫入到一個臨時文件中,待持久化過程結束了,再用這個臨時文件替換上次持久化還的文件。整個過程總,主進程是不進行任何 IO 操做,這就確保了極高的性能,若是須要進行大規模的數據恢復,且對於數據恢復的完整性不是很是敏感,那 RDB 方法要比 AOF 方式更加的高效。RDB 的缺點是最後一次持久化後的數據可能丟失。
Fork 的做用是複製一個與當前進程同樣的進程,新進程的全部數據(變量、環境變量、程序計數器等)數值都和原進程一致,可是是一個全新的進程,並做爲原進程的子進程
 
隱患:若當前的進程的數據量龐大,那麼 fork 以後數據量*2,此時就會形成服務器壓力大,運行性能下降
Rdb 保存的是 dump.rdb 文件
 

 
在測試:執行 flushAll 命令, 使用 shutDown 直接關閉進程時,第二次打開時 redis 會自動讀取 dump.rdb 文件,可是恢復時,全爲空。(此時的緣由:在關閉時刻,redis 系統會保存空的 dump.rdb 替換原來的緩存文件。因此第二次打開的 redis系統時候,自動讀取的是空值文件)

 
RDB save 操做
Rdb 是整個內存的壓縮的 snapshot,RDB 的數據結構,能夠配置符合快照觸發條件,默認的是 1 分鐘內改動 1 萬次,或者 5 分鐘改動 10 次,或者是 15 分鐘改動一次;
Save 禁用:若是想禁用 RDB 持久化的策略,只要不設置任何 save 指令,或者是給 save 傳入一個空字符串參數也能夠。
 
 -----> save 指令:即刻保存操做對象
 redis

如何觸發 RDB 快照

Save:save 時只管保存,其餘無論,所有阻塞。
Bgsave:redis 會在後臺進行快照操做,快照操做的同時還能夠響應客戶端的請求,能夠經過 lastsave 命令獲取最後一次成功執行快照的時間。
 
執行 fluhall 命令,也會產生 dump.rdb 文件,但裏面是空的。
 數據庫

如何恢復:

將備份文件(dump.rdb)移動到 redis 安裝目錄並啓動服務便可
Config get dir 命令可獲取目錄
 緩存

如何中止

動態中止 RDB 保存規則的方法:redis -cli config set save 「」
 
 安全

AOF(Append Only File)

以日誌的形式倆記錄每一個寫操做,將 redis 執行過的全部寫指令記錄下來(讀操做不記錄)。只許追加文件但不能夠改寫文件,redis 啓動之初會讀取該文件從新構建數據,換言之,redis重啓的話就根據日誌文件的內容將寫指令從前到後執行一次一完成數據恢復工做。
======APPEND ONLY MODE=====
 
開啓 aof :appendonly yes  (默認是 no)
 
 
 
 
注意:
 
 
在實際工做生產的時候每每會出現:aof 文件損壞(網絡傳輸或者其餘問題致使 aof 文件破壞)
 
 
 
 
 
服務器啓動報錯(可是 dump.rdb 文件是完整的) 說明啓動先加載 aof 文件
解決方案:執行命令 redis-check-aof --fix aof 文件 [自動檢查刪除不和 aof 語法的字段]
 服務器

Aof策略


 

 
Appendfsync 參數:
Always 同步持久化 每次發生數據變動會被當即記錄到磁盤,性能較差但數據完整性較好。
Everysec: 出廠默認推薦,異步操做,每秒記錄,日過一秒宕機,有數據丟失
No:從不 fsync :將數據交給操做系統來處理。更快,也更不安全的選擇。
 
 網絡

Rewrite

概念:AOF 採用文件追加方式,文件會愈來愈來大爲避免出現此種狀況,新增了重寫機制,aof 文件的大小超過所設定的閾值時,redis 就會自動 aof 文件的內容壓縮,值保留能夠恢復數據的最小指令集,可使用命令 bgrewirteaof。
重寫原理:aof 文件持續增加而大時,會 fork 出一條新進程來將文件重寫(也就
是先寫臨時文件最後再 rename),遍歷新進程的內存中的數據,每條記錄有一條 set 語句,重寫 aof 文件的操做,並無讀取舊的的 aof 文件,而是將整個內存的數據庫內容用命令的方式重寫了一個新的 aof 文件,這點和快照有點相似。
觸發機制:redis 會記錄上次重寫的 aof 的大小,默認的配置當 aof 文件大小上次 rewrite 後大小的一倍且文件大於 64M 觸發(3G)
 

 
 
no-appendfsync-on-rewrite no : 重寫時是否能夠運用 Appendfsync 用默認 no 便可,保證數據安全
auto-aof-rewrite-percentage  倍數 設置基準值
auto-aof-rewrite-min-size  設置基準值大小數據結構

AOF優勢

使用 AOF 持久化會讓 Redis 變得很是耐久:你能夠設置不一樣的 fsync 策略,好比無 fsync ,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。 AOF 的默認策略爲每秒鐘 fsync 一次,在這種配置下,Redis 仍然能夠保持良好的性能,而且就算髮生故障停機,也最多隻會丟失一秒鐘的數據( fsync 會在後臺線程執行,因此主線程能夠繼續努力地處理命令請求)。
AOF 文件是一個只進行追加操做的日誌文件(append only log), 所以對 AOF 文件的寫入不須要進行 seek , 即便日誌由於某些緣由而包含了未寫入完整的命令(好比寫入時磁盤已滿,寫入中途停機,等等), redis-check-aof 工具也能夠輕易地修復這種問題。
Redis 能夠在 AOF 文件體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操做是絕對安全的,由於 Redis 在建立新 AOF 文件的過程當中,會繼續將命令追加到現有的 AOF 文件裏面,即便重寫過程當中發生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件建立完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操做。
AOF 文件有序地保存了對數據庫執行的全部寫入操做, 這些寫入操做以 Redis 協議的格式保存, 所以 AOF 文件的內容很是容易被人讀懂, 對文件進行分析(parse)也很輕鬆。 導出(export) AOF 文件也很是簡單: 舉個例子, 若是你不當心執行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那麼只要中止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令, 並重啓 Redis , 就能夠將數據集恢復到 FLUSHALL 執行以前的狀態。app

AOF缺點

對於相同的數據集來講,AOF 文件的體積一般要大於 RDB 文件的體積。
根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在通常狀況下, 每秒 fsync 的性能依然很是高, 而關閉 fsync 可讓 AOF 的速度和 RDB 同樣快, 即便在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 能夠提供更有保證的最大延遲時間(latency)。
AOF 在過去曾經發生過這樣的 bug : 由於個別命令的緣由,致使 AOF 文件在從新載入時,沒法將數據集恢復成保存時的原樣。 (舉個例子,阻塞命令 BRPOPLPUSH 就曾經引發過這樣的 bug 。) 測試套件裏爲這種狀況添加了測試: 它們會自動生成隨機的、複雜的數據集,並經過從新載入這些數據來確保一切正常。雖然這種 bug 在 AOF 文件中並不常見, 可是對比來講, RDB 幾乎是不可能出現這種 bug 的。
 
 

備份Redis 數據

必定要備份你的數據庫!
磁盤故障, 節點失效, 諸如此類的問題均可能讓你的數據消失不見, 不進行備份是很是危險的。
Redis 對於數據備份是很是友好的, 由於你能夠在服務器運行的時候對 RDB 文件進行復制: RDB 文件一旦被建立, 就不會進行任何修改。 當服務器要建立一個新的 RDB 文件時, 它先將文件的內容保存在一個臨時文件裏面, 當臨時文件寫入完畢時, 程序才使用 rename(2) 原子地用臨時文件替換原來的 RDB 文件。
這也就是說, 不管什麼時候, 複製 RDB 文件都是絕對安全的。
建議:
建立一個按期任務(cron job), 每小時將一個 RDB 文件備份到一個文件夾, 而且天天將一個 RDB 文件備份到另外一個文件夾。
確保快照的備份都帶有相應的日期和時間信息, 每次執行按期任務腳本時, 使用 find 命令來刪除過時的快照: 好比說, 你能夠保留最近 48 小時內的每小時快照, 還能夠保留最近一兩個月的每日快照。
至少天天一次, 將 RDB 備份到你的數據中心以外, 或者至少是備份到你運行 Redis 服務器的物理機器以外。

容災備份

Redis 的容災備份基本上就是對數據進行備份, 並將這些備份傳送到多個不一樣的外部數據中心。
容災備份能夠在 Redis 運行併產生快照的主數據中心發生嚴重的問題時, 仍然讓數據處於安全狀態。
有的Redis 用戶是創業者, 他們沒有大把大把的錢能夠浪費, 因此下面介紹的都是一些實用又便宜的容災備份方法:
Amazon S3 ,以及其餘相似 S3 的服務,是一個構建災難備份系統的好地方。 最簡單的方法就是將你的每小時或者每日 RDB 備份加密並傳送到 S3 。 對數據的加密能夠經過 gpg -c 命令來完成(對稱加密模式)。 記得把你的密碼放到幾個不一樣的、安全的地方去(好比你能夠把密碼複製給你組織裏最重要的人物)。 同時使用多個儲存服務來保存數據文件,能夠提高數據的安全性。
傳送快照可使用 SCP 來完成(SSH 的組件)。 如下是簡單而且安全的傳送方法: 買一個離你的數據中心很是遠的 VPS(虛擬專用服務器) , 裝上 SSH , 建立一個無口令的 SSH 客戶端 key , 並將這個 key 添加到 VPS 的 authorized_keys 文件中, 這樣就能夠向這個 VPS 傳送快照備份文件了。 爲了達到最好的數據安全性,至少要從兩個不一樣的提供商那裏各購買一個 VPS 來進行數據容災備份。
須要注意的是, 這類容災系統若是沒有當心地進行處理的話, 是很容易失效的。
最低限度下, 你應該在文件傳送完畢以後, 檢查所傳送備份文件的體積和原始快照文件的體積是否相同。 若是你使用的是 VPS , 那麼還能夠經過比對文件的 SHA1 校驗和來確認文件是否傳送完整。
另外, 你還須要一個獨立的警報系統, 讓它在負責傳送備份文件的傳送器(transfer)失靈時通知你。
 
 

Redis主從複製

Redis 支持簡單且易用的主從複製(master-slave replication)功能, 該功能可讓從服務器(slave server)成爲主服務器(master server)的精確複製品。
如下是關於 Redis 複製功能的幾個重要方面:

  • Redis 使用異步複製。 從 Redis 2.8 開始, 從服務器會以每秒一次的頻率向主服務器報告複製流(replication stream)的處理進度。
  • 一個主服務器能夠有多個從服務器。
  • 不只主服務器能夠有從服務器, 從服務器也能夠有本身的從服務器, 多個從服務器之間能夠構成一個圖狀結構。
  • 複製功能不會阻塞主服務器: 即便有一個或多個從服務器正在進行初次同步, 主服務器也能夠繼續處理命令請求。
  • 複製功能也不會阻塞從服務器: 只要在 redis.conf 文件中進行了相應的設置, 即便從服務器正在進行初次同步, 服務器也可使用舊版本的數據集來處理命令查詢。

不過, 在從服務器刪除舊版本數據集並載入新版本數據集的那段時間內, 鏈接請求會被阻塞。
你還能夠配置從服務器, 讓它在與主服務器之間的鏈接斷開時, 向客戶端發送一個錯誤。

  • 複製功能能夠單純地用於數據冗餘(data redundancy), 也能夠經過讓多個從服務器處理只讀命令請求來提高擴展性(scalability): 好比說, 繁重的 SORT 命令能夠交給附屬節點去運行。
  • 能夠經過複製功能來讓主服務器免於執行持久化操做: 只要關閉主服務器的持久化功能, 而後由從服務器去執行持久化操做便可。

關閉主服務器持久化時,複製功能的數據安全

當配置Redis複製功能時,強烈建議打開主服務器的持久化功能。 不然的話,因爲延遲等問題,部署的服務應該要避免自動拉起。案例:
1. 假設節點A爲主服務器,而且關閉了持久化。 而且節點B和節點C從節點A複製數據
2. 節點A崩潰,而後由自動拉起服務重啓了節點A. 因爲節點A的持久化被關閉了,因此重啓以後沒有任何數據
3. 節點B和節點C將從節點A複製數據,可是A的數據是空的, 因而就把自身保存的數據副本刪除。
在關閉主服務器上的持久化,並同時開啓自動拉起進程的狀況下,即使使用Sentinel來實現Redis的高可用性,也是很是危險的。 由於主服務器可能拉起得很是快,以致於Sentinel在配置的心跳時間間隔內沒有檢測到主服務器已被重啓,而後仍是會執行上面的數據丟失的流程。
不管什麼時候,數據安全都是極其重要的,因此應該禁止主服務器關閉持久化的同時自動拉起。

從服務器配置

配置一個從服務器很是簡單, 只要在配置文件中增長如下的這一行就能夠了:
slaveof 192.168.1.1 6379
另一種方法是調用 SLAVEOF 命令,輸入主服務器的 IP 和端口,而後同步就會開始
127.0.0.1:6379> SLAVEOF 192.168.1.1 10086
OK

只讀從服務器

從 Redis 2.6 開始, 從服務器支持只讀模式, 而且該模式爲從服務器的默認模式。
只讀模式由 redis.conf 文件中的 slave-read-only 選項控制, 也能夠經過 CONFIG SET 命令來開啓或關閉這個模式。
只讀從服務器會拒絕執行任何寫命令, 因此不會出現由於操做失誤而將數據不當心寫入到了從服務器的狀況。
另外,對一個從屬服務器執行命令 SLAVEOF NO ONE 將使得這個從屬服務器關閉複製功能,並從從屬服務器轉變回主服務器,原來同步所得的數據集不會被丟棄。
利用『 SLAVEOF NO ONE 不會丟棄同步所得數據集』這個特性,能夠在主服務器失敗的時候,將從屬服務器用做新的主服務器,從而實現無間斷運行。
 
 

從服務器相關配置

 
若是主服務器經過 requirepass 選項設置了密碼, 那麼爲了讓從服務器的同步操做能夠順利進行, 咱們也必須爲從服務器進行相應的身份驗證設置。
對於一個正在運行的服務器, 可使用客戶端輸入如下命令:
config set masterauth
要永久地設置這個密碼, 那麼能夠將它加入到配置文件中:
masterauth

主服務器只在有至少 N 個從服務器的狀況下,才執行寫操做

從 Redis 2.8 開始, 爲了保證數據的安全性,能夠經過配置, 讓主服務器只在有至少 N 個當前已鏈接從服務器的狀況下, 才執行寫命令。
不過, 由於 Redis 使用異步複製, 因此主服務器發送的寫數據並不必定會被從服務器接收到, 所以, 數據丟失的可能性仍然是存在的。
如下是這個特性的運做原理:

  • 從服務器以每秒一次的頻率 PING 主服務器一次, 並報告複製流的處理狀況。
  • 主服務器會記錄各個從服務器最後一次向它發送 PING 的時間。
  • 用戶能夠經過配置, 指定網絡延遲的最大值 min-slaves-max-lag , 以及執行寫操做所需的至少從服務器數量 min-slaves-to-write 。

若是至少有 min-slaves-to-write 個從服務器, 而且這些服務器的延遲值都少於 min-slaves-max-lag 秒, 那麼主服務器就會執行客戶端請求的寫操做。另外一方面, 若是條件達不到 min-slaves-to-write 和 min-slaves-max-lag 所指定的條件, 那麼寫操做就不會被執行, 主服務器會向請求執行寫操做的客戶端返回一個錯誤。如下是這個特性的兩個選項和它們所需的參數:min-slaves-to-write <number of slaves>min-slaves-max-lag <number of seconds>  好了本篇文章就爲你們講解到這裏,感興趣的同窗能夠繼續關注咱們,下一篇文章將爲你們解密redis的sentinel(哨兵)機制和集羣模式,小夥伴們期待下次見面good-bye!

相關文章
相關標籤/搜索