1. 程式人生 > >Redis的資料儲存形式

Redis的資料儲存形式

redis的資料儲存方式

redis 提供持久化功能,把資料以檔案的方式持久化到硬碟中,但是目前大多都是redis配合關係資料庫使用,持久化仍然由關係資料完成,redis自身的持久化用於保證資料的安全性,以保證存放在redis的記憶體資料在沒有被全部被持久化到關係中如果redis伺服器發生災難資料的完整性。下面介紹redis兩種持久化方式。

1.Snapshotting即快照方式,儲存方式在redis.conf中的配置為 save 900 1 #當有一條Keys資料被改變時,900秒重新整理到Disk一次

save 300 10 #當有10條Keys資料被改變時,300秒重新整理到Disk一次

save 60 10000 #當有10000條Keys資料被改變時,60秒重新整理到Disk一次 可根據需求修改,當記憶體資料的變動滿足如上配置時,redis會給但是記憶體資料做snapshot,完整儲存當時記憶體資料狀態,檔案儲存在dump.rdb中,當做一次新的snapshot時,程序會把此時的記憶體的snapshot寫在一個臨時檔案中,當臨時檔案寫完,用新寫的臨時檔案替換原有的dump.rdb檔案,並刪除舊的 RDB 檔案。。每次快照持久化都是將記憶體資料完整寫入到磁碟一次,並不是增量的只同步髒資料。如果資料量大的話,而且寫操作比較多,必然會引起大量的磁碟io操作,可能會嚴重影響效能。

另外由於快照方式是在一定間隔時間做一次的,所以如果redis意外down掉的話,就會丟失最後一次快照後的所有修改。

2.aof方式,aof方式是以日誌的方式來儲存資料,即它將記錄每次對於redis的操作,每一次操作都有一條相應的記錄,因此aof方式產生的檔案比snapshot方式要大。比如set test 1然後呼叫 100次 incr test,則aof方式會儲存這100次操作,但是對於客戶端有用的卻只是最後一次修改後的值,如果此時做了snapshot,則dump.rdb檔案只是儲存了最後一次操作後的值,而appendonly.aof則儲存了每一次操作的記錄。aof方式在配置檔案中的體現

appendonly yes #開啟aof方式

appendfsync always //每次收到寫命令就立即強制寫入磁碟,最慢的,但是保證完全的持久化,不推薦使用

appendfsync everysec //每秒鐘強制寫入磁碟一次,在效能和持久化方面做了很好的折中,推薦

appendfsync no //完全依賴os,效能最好,持久化沒保證

因為aof的追加方式會產生冗餘,為了壓縮aof的持久化檔案。redis提供了bgrewriteaof命令。收到此命令redis將使用與快照類似的方式將記憶體中的資料 以命令的方式儲存到臨時檔案中,最後替換原來的檔案。具體過程如下

  1. redis呼叫fork ,現在有父子兩個程序

  2. 子程序根據記憶體中的資料庫快照,往臨時檔案中寫入重建資料庫狀態的命令

3.父程序繼續處理client請求,除了把寫命令寫入到原來的aof檔案中。同時把收到的寫命令快取起來。這樣就能保證如果子程序重寫失敗的話並不會出問題。

4.當子程序把快照內容寫入已命令方式寫到臨時檔案中後,子程序發訊號通知父程序。然後父程序把快取的寫命令也寫入到臨時檔案。

5.現在父程序可以使用臨時檔案替換老的aof檔案,並重命名,後面收到的寫命令也開始往新的aof檔案中追加。

需要注意到是重寫aof檔案的操作,並沒有讀取舊的aof檔案,而是將整個記憶體中的資料庫內容用命令的方式重寫了一個新的aof檔案,這點和快照有點類似。

RDB 的優點

RDB 是一個非常緊湊(compact)的檔案,它儲存了 Redis 在某個時間點上的資料集。 這種檔案非常適合用於進行備份: 比如說,你可以在最近的 24 小時內,每小時備份一次 RDB 檔案,並且在每個月的每一天,也備份一個 RDB 檔案。 這樣的話,即使遇上問題,也可以隨時將資料集還原到不同的版本。

RDB 非常適用於災難恢復(disaster recovery):它只有一個檔案,並且內容都非常緊湊,可以(在加密後)將它傳送到別的資料中心,或者亞馬遜 S3 中。

RDB 可以最大化 Redis 的效能:父程序在儲存 RDB 檔案時唯一要做的就是 fork 出一個子程序,然後這個子程序就會處理接下來的所有儲存工作,父程序無須執行任何磁碟 I/O 操作。

RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。

RDB 的缺點

如果你需要儘量避免在伺服器故障時丟失資料,那麼 RDB 不適合你。 雖然 Redis 允許你設定不同的儲存點(save point)來控制儲存 RDB 檔案的頻率, 但是, 因為RDB 檔案需要儲存整個資料集的狀態, 所以它並不是一個輕鬆的操作。 因此你可能會至少 5 分鐘才儲存一次 RDB 檔案。 在這種情況下, 一旦發生故障停機, 你就可能會丟失好幾分鐘的資料。

每次儲存 RDB 的時候,Redis 都要 fork() 出一個子程序,並由子程序來進行實際的持久化工作。 在資料集比較龐大時, fork() 可能會非常耗時,造成伺服器在某某毫秒內停止處理客戶端; 如果資料集非常巨大,並且 CPU 時間非常緊張的話,那麼這種停止時間甚至可能會長達整整一秒。 雖然 AOF 重寫也需要進行 fork() ,但無論 AOF 重寫的執行間隔有多長,資料的耐久性都不會有任何損失。

鑑於RDB的缺點對於我們專案的應用來說是致命的,因此不考慮使用此種方式。

AOF 的優點

使用 AOF 持久化會讓 Redis 變得非常耐久(much more durable):你可以設定不同的 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 執行之前的狀態。

AOF 的缺點

對於相同的資料集來說,AOF 檔案的體積通常要大於 RDB 檔案的體積。

根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在一般情況下, 每秒 fsync 的效能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。

RDB 和 AOF ,我應該用哪一個?

一般來說, 如果想達到足以媲美 PostgreSQL 的資料安全性, 你應該同時使用兩種持久化功能。

如果你非常關心你的資料, 但仍然可以承受數分鐘以內的資料丟失, 那麼你可以只使用 RDB 持久化。

有很多使用者都只使用 AOF 持久化, 但我們並不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便於進行資料庫備份, 並且 RDB 恢復資料集的速度也要比 AOF 恢復的速度要快