共計 3605 個字符,預計需要花費 10 分鐘才能閱讀完成。
Redis 持久化的運行機制和優缺點是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
前言
大家都知道 Redis 一個內存數據庫, 它支持 2 種持久化方式:RDB(Snapshot 內存快照),AOF(append only file)。持久化功能將內存中的數據同步到磁盤來避免 Redis 發生異常導致數據丟失的情況。當 Redis 實例重啟時,即可利用之前持久化的文件實現數據恢復。
接下來,丸趣 TV 小編介紹兩種持久化的運行機制和優缺點。
一 RDB
RDB 是默認的持久化方式,按照一定的策略周期性的將內存中的數據生成快照保存到磁盤。
每次快照持久化都是將內存數據完整寫入到磁盤一次,并不 是增量的只同步臟數據。如果數據量大的話,而且寫操作比較多,必然會引起大量的磁盤 io 操作,可能會嚴重影響性能。
1.1 快照持久化過程
1.2 觸發機制
1. save 命令
當客戶端向 Redis server 發送 save 命令請求進行持久化時,由于 Redis 是用一個主線程來處理所有,save 命令會阻塞 Redis server 處理其他客戶端的請求,直到數據同步完成。
2. bgsave 命令
與 save 命令不同,bgsave 是異步執行的,當執行 bgsave 命令之后,Redis 主進程會 fork 一個子進程將數據保存到 rdb 文件中,同步完數據之后,對原有文件進行替換,然后通知主進程表示同步完成。
3. 自動觸發
除了手動觸發 RDB 持久化,Redis 內部還存在自動觸發機制,
在配置中集中配置 save m n 的方式,表示 m 秒內數據集存在 n 次修改時,系統自動觸發 bgsave 操作。
# 900s 內至少達到一條寫命令 save 900 1 # 300s 內至少達至 10 條寫命令 save 300 10 # 60s 內至少達到 10000 條寫命令 save 60 10000
從節點執行全量復制操作,主節點自動執行 bgsave 生成 RDB 文件并發送給從節點
默認情況下執行 shutdown 命令時,如果沒有開啟 AOF 持久化功能,系統會自動執行 bgsave 命令。執行 debug reload 命令重新加載 Redis 時,也會自動觸發 save 操作。
1.3 相關參數
# 持久化 rdb 文件遇到問題時,主進程是否接受寫入,yes 表示停止寫入,如果是 no 表示 redis 繼續提供服務。 stop-writes-on-bgsave-error yes # 在進行快照鏡像時, 是否進行壓縮。yes: 壓縮,但是需要一些 cpu 的消耗。no: 不壓縮,需要更多的磁盤空間。 rdbcompression yes # 一個 CRC64 的校驗就被放在了文件末尾,當存儲或者加載 rbd 文件的時候會有一個 10% 左右的性能下降,為了達到性能的最大化,你可以關掉這個配置項。 rdbchecksum yes # 快照的文件名 dbfilename dump.rdb # 存放快照的目錄 dir /var/lib/redis
1.4 RDB 的優缺點
優點
RDB 文件小,非常適合定時備份,用于災難恢復。
因為 RDB 文件中直接存儲的是內存數據,而 AOF 文件中存儲的是一條條命令,需要應用命令。Redis 加載 RDB 文件的速度比 AOF 快很多。
缺點
RDB 持久化方式不能做到實時 / 秒級持久化。實時持久化要全量刷內存到磁盤,成本太高。每秒 fork 子進程也會阻塞主進程,影響性能。
RDB 文件是二進制文件,隨著 Redis 不斷迭代有多個 rdb 文件的版本,不支持跨版本兼容。老的 Redis 無法識別新的 RDB 文件格式。
二 AOF
AOF(Append-only file) 針對 RDB 的缺點做了優化,在使用 AOF 持久化方式時,Redis 會將每一個收到的寫操作命令都通過 Write 函數追加到文件最后,類似于 MySQL 的 binlog。當 Redis 重啟時會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。
2.1 AOF 持久化過程
1. 客戶端發出 bgrewriteaof 命令。
2. redis 主進程 fork 子進程。
3. 父進程繼續處理 client 請求,除了把寫命令寫入到原來的 aof 文件中。同時把收到的寫命令緩存到 AOF 重寫緩沖區。這樣就能保證如果子進程重寫失敗的話并不會出問題。
4. 子進程根據內存快照,按照命令合并規則寫入到新 AOF 文件中。
5. 當子進程把內存快照寫入臨時文件中后,子進程發信號通知父進程。然后父進程把緩存的寫命令也寫入到臨時文件。
6. 現在父進程可以使用臨時文件替換老的 aof 文件,并重命名,后面收到的寫命令也開始往新的 aof 文件中追加。
2.2 相關參數
# 是否開啟 AOF,默認關閉 appendonly yes # 指定 AOF 文件名 appendfilename appendonly.aof # Redis 支持三種刷寫模式: # appendfsync always #每次收到寫命令就立即強制寫入磁盤,類似 MySQL 的 sync_binlog=1, 是最安全的。但該模式下速度也是最慢的,一般不推薦使用。 appendfsync everysec #每秒鐘強制寫入磁盤一次,在性能和持久化方面做平衡,推薦該方式。 # appendfsync no #完全依賴 OS 的寫入,一般為 30 秒左右一次,性能最好但是持久化最沒有保證,不推薦。 #在日志重寫時,不進行命令追加操作,而只是將其放在緩沖區里,避免與命令的追加造成 DISK IO 上的沖突。 #設置為 yes 表示 rewrite 期間對新寫操作不 fsync, 暫時存在內存中, 等 rewrite 完成后再寫入,默認為 no,建議 yes no-appendfsync-on-rewrite yes #當前 AOF 文件大小是上次日志重寫得到 AOF 文件大小的二倍時,自動啟動新的日志重寫過程。 auto-aof-rewrite-percentage 100 # 當前 AOF 文件啟動新的日志重寫過程的最小值,避免剛剛啟動 Reids 時由于文件尺寸較小導致頻繁的重寫。 auto-aof-rewrite-min-size 64mb
2.3 日志重寫
AOF 機制將客戶端的每一個寫操作都追加到 aof 文件末尾,比如將一個 key 多次執行 incr,set 命令, 會寫入多次命令到 aof 文件,aof 文件會越來越大,部分核心業務每天的寫入量有幾十 G 的大小。
incr k1 1 set k2 a set k2 b incr k1 2 incr k1 3 set k2 c del k3 ... incr k1 100
恢復 Redis 實例時,加載非常大的 aof 文件耗時會很長。為了解決這個問題,Redis 支持 aof 文件重寫 – 把 Redis 進程內的數據轉化為寫命令同步到新 AOF 文件中的過程。通過重寫,可以生成一個最小的命令集合。比如上面的幾個命令可以合并為
incr k1 100 set k2 c
寫入數據的規則
1. 進程內過期的數據不用在寫入
2. 舊 AOF 文件含有的無效命令 del k1, set a 1, set a 2。重寫使用進程內的數據直接生成,aof 文件就保留最新的命令集合。
3. 多條命令可以合并為一個命令,為了防止單個命令過大造成客戶端緩沖區溢出,對于 list,set,hash,zset 等類型的操作,以 64 個元素為界拆分為多條。
觸發機制
1. 手動觸發 執行 bgrewriteaof 命令。
2. 根據配置自動觸發
auto-aof-rewrite-min-size 表示運行 AOF 重寫是文件最小的大小。默認 64M,小于 64M 就會不自動重寫了。
auto-aof-rewrite-percentage 表示(aof_current_size- aof_base_size)/ aof_base_size 的比值。
aof 文件重寫之后當前文件大小增長多少就觸發重寫
自動觸發時機 :
aof_current_size auto-aof-rewrite-min-size
(aof_current_size – aof_base_size) / aof_base_size = auto-aof-rewrite-percentage
三 RDB VS AOF 對比
具體使用哪種持久化方式,下面是來自官方的建議:
通常,如果你要想提供很高的數據保障性,那么建議你同時使用兩種持久化方式。如果你可以接受災難帶來的幾分鐘的數據丟失,那么你可以僅使用 RDB。很多用戶僅使用了 AOF,但是我們建議,既然 RDB 可以時不時的給數據做個完整的快照,并且提供更快的重啟,所以最好還是也使用 RDB。
生產上的實例大多不會是單點,而是主從,也有利用 slave 作為持久化方式,同時滿足 HA 的需求。讀者朋友可以分享一下各自遇到的和 redis 持久化相關的問題。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注丸趣 TV 行業資訊頻道,感謝您對丸趣 TV 的支持。