細說Redis持久化機制
概述
Redis不僅能夠作為緩存來使用,也能夠作為內存數據庫。
Redis作為內存數據庫使用時。必需要解決一個問題:數據的持久性。有些將Redis作為緩存使用的場景也需要將緩存的數據持久化到存儲介質上,這樣在Redis重新啟動後仍然能對熱點數據提供緩存服務。不會由於緩存數據的缺失而對整個系統造成沖擊。
本文就Redis內置的持久化機制進行說明。
Redis持久化方式
Redis內置的持久化方式有兩種:快照方式和AOF方式。
快照方式是將某一時點的內存數據寫到硬盤上。AOF方式是將寫入的命令記錄在硬盤上的文件中。以下具體說明這兩種方式。
快照方式
快照方式能夠將一個時點的內存數據保存到硬盤。保存快照之後Redis重新啟動時能夠讀取快照文件而恢復數據,也能夠使用快照來建立復制相應的Redisserver。
快照持久化模式
既然快照是保存某一個時點的內存數據,那麽就要求在進行快照時內存數據不能發生變化。關於這點Redis有兩種模式:SAVE和BGSAVE。SAVE模式首先使Redis停止服務,然後將這個時點的Redis內存數據寫入到硬盤中。等完畢寫入後Redis開始提供服務,這個過程通常會比較長,在生產環境中使用的場景較少。
BGSAVE模式會使用fork命令拷貝Redis的內存,在fork過程中Redis也會停止對外服務,但這個過程很快。在實體機或者VMWare和KVM中1G的內存拷貝大概在10-20ms,而在Xen中要稍慢些,大概在200-300ms。
拷貝內存完畢後,拷貝的這份內存數據開始持久化到硬盤。同一時候Redis也繼續對外提供服務。
SAVE模式對Redis可用性影響非常大。可能使Redis在一段較長時間內無法提供服務。BGSAVE模式對Redis可用性影響較小,1G的內存數據會使Redis中斷服務10-20ms。這個數值在普通情況下是能夠接受的,可是由於BGSAVE是使用fork機制,這就要求fork時系統的可用內存至少要和Redis占用的內存一樣大。
快照的觸發條件
觸發Redis進行內存快照持久的條件有下面幾種:
- 給Redisserver發送BGSAVE命令,這將觸發Redis進行BGSAVE模式的快照持久。
- 給Redisserver發送SAVE命令。這將觸發Redis進行SAVE模式的快照持久。
- Redis接收到SHUTDOWN命令或者TERM信號,將觸發Redis進行SAVE模式的快照持久。之後Redis停止。
- 在主從結構中。當從Redis同步主Redis時間太長時。主Redis會觸發BGSAVE模式的快照持久。
- 在配置文件的save屬性中配置Redis在某個條件滿足時進行持久,這會觸發Redis進行BGSAVE模式的持久。比如,在配置文件裏配置`save 60 10000`。意為假設在60s內發生了10000次寫操作那麽Redis將啟動BGSAVE操作。在配置文件裏能夠配置多個save,當有一個save條件滿足時。Redis就運行BGSAVE操作。
快照配置的參數
參數名稱 | 參數值 | 參數解釋 |
save | m秒 n次,比方60 1000 | 配置觸發快照的條件。"60 1000"表示假設在60s內發生了1000次寫操作。那麽Redis就要進行持久操作 |
stop-writes-no-bgsave-error | yes,no | 配置在BGSAVE錯誤發生時是否停止 |
rdbcompression | yes,no | 配置是否對持久數據進行壓縮 |
dir | 文件夾路徑,比方./ | 配置持久文件保存的文件夾 |
dbfilename | 持久文件名稱。比方dump.rdb | 配置持久文件名稱 |
快照存在的問題
從上面的說明能夠看出,快照持久化方式是基於時間點的,假設在一次快照完畢,下一次快照還沒開始之前Redis崩潰了,那麽上一快照之後的數據變化將會丟失。
在BGSAVE模式下,假設在快照剛結束時Redis崩潰,那將會丟失內存拷貝之後的發生變化的數據。
AOF方式
AOF方式將Redis每次的寫操作都保存在日誌文件裏。通過回放日誌文件Redis就可以恢復全部的數據。Redis將每次寫操作的日誌都保存在內存的一個緩存區中而不是即時寫入硬盤,Redis提供了三種方式將內存日誌同步到硬盤。
文件同步方式
- always : Redis在每次有寫操作發生時都會同步到硬盤,這樣的方式會給IO帶來非常大壓力,實際中寫入的速率要考慮硬盤的IO速率。
- everysec :Redis每1秒將日誌同步到硬盤。這樣的方式性能較好,但也意為著假設Redis崩潰那麽將丟失1秒的數據。
- no : Redis不主動控制內存緩存區和硬盤的同步,而由操作系統來控制。
這樣的方式不可控,一般不採用。
Rewriting/compacting AOF
AOF方式各方面比較均衡。可是有個缺點:隨著Redis的執行硬盤上的日誌文件將會越來越大,將會占用大量硬盤空間,並且在Redis重新啟動時也會由於日誌文件太大而須要非常長的啟動時間。為了解決問題Redis提供了BGREWRITEAOF命令來重建日誌。
BGREWRITEAOF執行機制
BGREWRITEAOF執行機制和BGSAVE非常類似:使用fork創建拷貝進程,然後再將拷貝內存中的數據寫入到暫時的日誌文件裏。完畢寫入後再用rename原子操作替換掉日誌文件。BGREWRITEAOF存在的問題
BGREWRITEAOF同BGSAVE一樣有著下面問題:- fork時要暫停Redis對外服務
- 須要系統為fork保留內存空間
- 由於要替換日誌文件,假設日誌文件很大。比方幾十G,那麽替換日誌文件的時間也會比較長。
AOF配置的參數
AOF配置的參數
參數名稱 | 參數值 | 參數解釋 |
appendonly | yes,no | 配置是否開啟AOF持久機制 |
appendfsync | always,everysec,no | 配置AOF持久機制的同步策略 |
no-appendfsync-on-rewirte | yes,no | 配置在重建日誌時是否繼續進行AOF |
auto-aof-rewrite-percentage | 百分比值 比方100 |
配置觸發重建日誌的條件:當前日誌大小和最後一次重建日誌大小的比例,這裏的"100"意為當前日誌大小超過最後一次重建日誌大小100%時。將可能觸發重建日誌操作。 |
auto-aof-rewrite-min-size | 日誌文件大小 比方64mb |
配置觸發重建日誌的條件:當前日誌大小的最小值,這裏的"64mb"意為當前日誌超過64mb時,將可能觸發重建日誌操作。 要註意的是:auto-aof-rewrite-percentage和auto-aof-rewrite-min-size必須同一時候滿足才幹夠觸發重建日誌操作。 |
dir | 文件夾路徑 比方./ |
配置持久文件保存的文件夾 |
持久化方式比較
分析了Redis的快照和AOF持久機制,在實際生產環境中部署該選擇哪種方式呢?以下從Redis可用性影響、數據丟失、內存占用、IO負荷、硬盤空間占用幾個維度比較各持久化方式:持久化方式 | 可用性影響 | 數據丟失 | 內存占用 | IO負荷 | 硬盤空間占用 |
SAVE | 高 | 分鐘級 | 小 | 高 | 較低 |
BGSAVE | 較小 | 分鐘級 | 大 | 高 | 較低 |
AOF | 小 | 秒級 | 小 | 較高 | 高 |
AOF+BGREWRITEAOF | 較小 | 秒級 | 大 | 最高 | 較高 |
從上表能夠看出AOF或者AOF+BGREWRITEAOF方式在一般場景下應該是優先考慮的持久化方式。
細說Redis持久化機制