1. 程式人生 > >redis的持久化:AOF的配置和原理

redis的持久化:AOF的配置和原理

RDB最大的不足之處在於:一旦資料庫出現問題,由於RDB檔案中儲存的資料並不是全新的。從上次RDB檔案生成到redis宕機,這段時間的資料全部丟掉了(因為刷寫機制還沒有出發)。

AOF比RDB有更好的永續性。在使用AOF的時候,redis會將每一個收到的寫命令都通過write()系統函式追加到aof檔案中,類似於MySQL的binlog。當redis重啟後,會通過重新執行檔案中儲存的寫命令來在記憶體中重建整個資料庫的內容。

AOF的完全持久化方式同時也帶來了另一個問題,持久化檔案會變得越來越大。(比如我們呼叫INCR test命令100次,檔案中就必須儲存全部的100條命令,但其實99條都是多餘的。因為要恢復資料庫的狀態其實檔案中儲存一條SET test 100就夠了)。為了壓縮AOF的持久化檔案,Redis提供了bgrewriteaof命令。收到此命令後Redis將使用與快照類似的方式將記憶體中的資料以命令的方式儲存到臨時檔案中,最後替換原來的檔案,以此來實現控制AOF檔案的增長。

redis與aof相關配置如下:

############################## APPEND ONLY MODE ###############################
# 是否開啟AOF,預設關閉(no)
appendonly yes

# 指定 AOF 檔名
appendfilename appendonly.aof

# Redis支援三種不同的刷寫模式:
# appendfsync always #每次收到寫命令就立即強制寫入磁碟,是最有保證的完全的持久化,但速度也是最慢的,一般不推薦使用。
appendfsync everysec #每秒鐘強制寫入磁碟一次,在效能和持久化方面做了很好的折中,是受推薦的方式。
# appendfsync no     #完全依賴OS的寫入,一般為30秒左右一次,效能最好但是持久化最沒有保證,不被推薦。

#在日誌重寫時,不進行命令追加操作,而只是將其放在緩衝區裡,避免與命令的追加造成DISK IO上的衝突。
#設定為yes表示rewrite期間對新寫操作不fsync,暫時存在記憶體中,等rewrite完成後再寫入,預設為no
no-appendfsync-on-rewrite no 

#當前AOF檔案大小是上次日誌重寫得到AOF檔案大小的二倍時,自動啟動新的日誌重寫過程。
auto-aof-rewrite-percentage 100

#當前AOF檔案啟動新的日誌重寫過程的最小值,避免剛剛啟動Reids時由於檔案尺寸較小導致頻繁的重寫。
auto-aof-rewrite-min-size 64mb

關於redis的重新整理模式和日誌重寫:

由於寫操作通常是有緩衝的,所以有可能AOF操作並沒有寫到硬碟中,一般可以通過fsync()來強制輸出到硬碟中。而fsync()的頻率可以通過配置檔案中的flush策略來指定,可以選擇每次事件迴圈寫操作都強制fsync或者每秒fsync至少執行一次。

當rewrite子程序開始後,父程序接受到的命令會新增到aof_rewrite_buf_blocks中,使得rewrite成功後,將這些命令新增到新檔案中。在rewrite過程中,原來的AOF也可以選擇是不是繼續新增,由於存在效能上的問題,在rewrite過程中,如果fsync()繼續執行,會導致IO效能受損影響Redis效能。所以一般情況下rewrite期間禁止fsync()到舊AOF檔案。這策略可以在配置檔案中修改。