有道無術,術尚可求,有術無道,止于術。
本系列Redis 版本 7.2.5
源碼地址:https://gitee.com/pearl-organization/study-redis-demo
文章目錄
- 1. 概述
- 2. 執行原理
- 2.1 Redis 6.x
- 2.1.1 直接寫
- 2.1.2 重寫
- 2.2 Redis 7.x
- 2.2.1 Redis 6 AOF 中的
- 2.2.
- 2. 配置項
- 2.1 appendonly
- 2.2 appendfilename
- 2.3 appenddirname
- 2.4 appendfsync
- 2.5 no-appendfsync-on-rewrite
- 2.6 auto-aof-rewrite-percentage、auto-aof-rewrite-min-size
- 2.7 aof-load-truncated
- 2.8 aof-use-rdb-preamble
- 2.9 aof-timestamp-enabled
1. 概述
默認情況下,Redis
使用RDB
持久化,但如果進程出現問題或電源中斷,可能會導致幾分鐘的寫入數據丟失(具體取決于配置的保存點)。
Append Only File
(AOF
)是另一種持久化模式,它提供了更好的持久性保證。AOF
以日志的形式來記錄每個寫操作,Redis
重啟時通過讀取和執行AOF
文件中的命令來重建數據集。
2. 執行原理
2.1 Redis 6.x
Redis 6
及之前的版本中,生成的 AOF
只有一個,整個執行流程如下:
2.1.1 直接寫
Redis
在執行寫操作時,并不是將指令直接寫入到文件中,而是先寫入到緩沖區(aof_buf
),然后根據相應的策略同步( fsync
)到磁盤中,支持以下三種不同的模式(后面配置有詳細介紹):
no
:操作系統自行決定always
:每次寫入都會立即被刷新到磁盤everysec
:每秒只進行一次fsync
調用
寫入的 AOF
文件如下所示:
當 Redis
宕機重啟時,可以通過讀取和執行 AOF
文件中的命令來重建數據集。但是每一次寫指令都會存入到 AOF
文件,可能會導致文件變得非常大,文件太大時,無論是寫入還是加載都會變得特別慢。
2.1.2 重寫
為了避免 AOF
文件多大問題,控制文件大小并優化性能,Redis
支持運行時觸發 AOF
文件重寫(rewrite
),用以壓縮 AOF
文件的大小。
重寫機制可以通過 BGREWRITEAOF
命令手動觸發,也可以自動觸發,配置參數如下:
# 當 AOF 文件大小超過上次重寫后 AOF 文件大小的百分比時自動觸發,默認值為 100
auto-aof-rewrite-percentage 100
# 當 AOF 文件大小超過指定值時自動觸發,默認值為 64 MB
auto-aof-rewrite-min-size 64mb
當觸發重寫機制后, Redis
主進程會阻塞等待(微秒級)并執行 fork
創建子進程,創建完成后,會繼續接收新的請求命令,并將 fork
后的寫操作寫入到緩沖區并刷盤。此外新操作還會寫入到重寫緩沖區(aof_rewrite_buf
)中,以便重寫完成后合并到新文件中,確保和內存數據的一致性。
重寫子進程會根據當前時刻 Redis
的數據快照,將每個鍵值對轉換為相應的寫入命令,并寫入到一個臨時文件中 ( temp-rewriteaof-bg-pid.aof
)。當上述操作完成后,主進程會將重寫緩沖區中的數據發送給子進程,由子進程將數據追加到臨時AOF
文件中。
子進程重寫完成后,會發送消息給主進程,主進程負責將重寫緩沖區(可能存在未發送的數據)中剩余數據繼續追加到臨時AOF
文件,并執行原子性的重命名操作,覆蓋原先的AOF
文件,至此整個重寫流程結束。
在子進程重寫的后期階段,主進程會將aof_rewrite_buf中累積的數據使用pipe發送給子進程,子進程會將這些數據追加到臨時AOF文件中(詳細原理可參考[1])。
當主進程承接了較大的寫入流量時,aof_rewrite_buf中可能會堆積非常多的數據,導致在重寫期間子進程無法將aof_rewrite_buf中的數據全部消費完。此時,aof_rewrite_buf剩余的數據將在重寫結束時由主進程進行處理。
當子進程完成重寫操作并退出后,主進程會在backgroundRewriteDoneHandler 中處理后續的事情。首先,將重寫期間aof_rewrite_buf中未消費完的數據追加到臨時AOF文件中。其次,當一切準備就緒時,Redis會使用rename 操作將臨時AOF文件原子的重命名為server.aof_filename,此時原來的AOF文件會被覆蓋。至此,整個AOFRW流程結束。
-
子進程完成重寫
5.1 新?件寫?后,5.2 父進程將AOF重寫緩存區內臨時保存的新命令追加到新AOF文件中5.3 用新的AOF文件替換舊的的AOF文
AOF 重寫機制是通過 fork 出一個子進程來完成的,子進程會掃描 Redis 的數據庫,并,然后。
在子進程進行 AOF 重寫的過程中,主進程還會繼續接收和處理客戶端的請求,如果有新的寫操作發生,主進程會將這些寫操作追加到一個緩沖區中,并通過管道通知子進程 。
子進程在完成 AOF 重寫后,會將緩沖區中的寫操作也追加到臨時文件中,然后向主進程發送信號,通知主進程可以切換到新的 AOF 文件了 。
主進程在收到子進程的信號后,會將緩沖區中的寫操作再次追加到臨時文件中(以防止在此期間有新的寫操作發生),然后用臨時文件替換舊的 AOF 文件,并關閉舊的 AOF 文件 。
全部重寫到臨時 AOF
文件中,名稱為 ,
全部。
AOF重寫是Redis用來優化AOF文件大小和性能的過程。在AOF重寫過程中,Redis會執行以下步驟:
啟動AOF重寫進程:Redis會啟動一個后臺進程來執行AOF重寫操作。
生成臨時文件:在AOF重寫過程中,Redis會創建一個臨時的AOF文件,類似于"temp-rewriteaof-bg-pid.aof"。這個臨時文件會用來存儲重寫期間生成的新的AOF日志。
重寫AOF文件:Redis會遍歷當前數據集,將其中的命令操作重寫到臨時AOF文件中。重寫的目標是優化AOF文件的結構和內容,以減少文件大小和改善讀寫性能。
完成重寫并替換舊文件:一旦AOF重寫完成,Redis會將新生成的AOF文件重命名為原始的AOF文件名(例如默認的redis.aof),以及刪除舊的AOF文件。
因此,"temp-rewriteaof-bg-pid.aof"文件是Redis AOF重寫過程中生成的臨時文件,用于在重寫期間暫存新生成的AOF數據。
該操作會將執行fork那一刻
由于重寫操作為子進程后臺執行,主進程在AOF重寫期間依然可以正常響應用戶命令。因此,為了讓子進程最終也能獲取重寫期間主進程產生的增量變化,主進程除了會將執行的寫命令寫入aof_buf,還會寫一份到aof_rewrite_buf中進行緩存。在子進程重寫的后期階段,主進程會將aof_rewrite_buf中累積的數據使用pipe發送給子進程,子進程會將這些數據追加到臨時AOF文件中(詳細原理可參考[1])。
當主進程承接了較大的寫入流量時,aof_rewrite_buf中可能會堆積非常多的數據,導致在重寫期間子進程無法將aof_rewrite_buf中的數據全部消費完。此時,aof_rewrite_buf剩余的數據將在重寫結束時由主進程進行處理。
當子進程完成重寫操作并退出后,主進程會在backgroundRewriteDoneHandler 中處理后續的事情。首先,將重寫期間aof_rewrite_buf中未消費完的數據追加到臨時AOF文件中。其次,當一切準備就緒時,Redis會使用rename 操作將臨時AOF文件原子的重命名為server.aof_filename,此時原來的AOF文件會被覆蓋。至此,整個AOFRW流程結束。
-
首先執行AOF重寫請求,如果當前進程正在執? AOF 重寫,請求不執?。如果當前進程
正在執? bgsave 操作,重寫命令延遲到 bgsave 完成之后再執?
-
父(很快單位以微秒記)執行,創建出
-
重寫
3.1 當父進程fork之后,繼續響應其他命令。所有修改操作寫? AOF 緩沖區并根據 appendfsync策略同步到硬盤,保證舊 AOF ?件機制正確3.2 ?進程只有 fork 之前的所有內存信息,?進程中需要將 fork 之后這段時間的修改操作寫? AOF 重寫緩沖區中
-
?進程根據內存快照,將命令合并到新的 AOF ?件中(這里就是壓縮后的文件)
————————————————
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
原文鏈接:https://blog.csdn.net/x2656271356/article/details/134446175
為了控制文件大小并優化性能,Redis 提供了 AOF 重寫機制。AOF 重寫不改變實際數據,而是創建一個新的 AOF 文件,其中包含當前數據集的最小命令集合,可以完整地重構數據集。
AOF 重寫是通過讀取現有數據集并使用簡化的命令來重建新的 AOF 文件來實現的,新文件可以替代舊文件,從而達到壓縮和優化的目的。
1:在重寫開始前,redis會創建一個“重寫子進程”,這個子進程會讀取現有的AOF文件,并將其包含的指令進行分析壓縮并寫入到一個臨時文件中。
2:與此同時,主進程會將新接收到的寫指令一邊累積到內存緩沖區中,一邊繼續寫入到原有的AOF文件中,這樣做是保證原有的AOF文件的可用性,避免在重寫過程中出現意外。
3:當“重寫子進程”完成重寫工作后,它會給父進程發一個信號,父進程收到信號后就會將內存中緩存的寫指令追加到新AOF文件中
4:當追加結束后,redis就會用新AOF文件來代替舊AOF文件,之后再有新的寫指令,就都會追加到新的AOF文件中
5:重寫aof文件的操作,并沒有讀取舊的aof文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的aof文件,這點和快照有點類似
由用戶手動觸發,也可以由系統自動觸發 。
用戶手動觸發 AOF 重寫機制可以通過執行 BGREWRITEAOF 命令來實現 。
系統自動觸發 AOF 重寫機制可以通過配置文件中的 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 參數來控制 。
auto-aof-rewrite-percentage 參數表示觸發 AOF 重寫機制,
auto-aof-rewrite-min-size 參數表示當才可能 AOF 重寫機制, 。
AOF 重寫機制的觸發方式
AOF 重寫機制可以由用戶手動觸發,也可以由系統自動觸發 。
用戶手動觸發 AOF 重寫機制可以通過執行 BGREWRITEAOF 命令來實現 。
系統自動觸發 AOF 重寫機制可以通過配置文件中的 auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size 參數來控制 。
auto-aof-rewrite-percentage 參數表示當當前 AOF 文件大小超過上次重寫后 AOF 文件大小的百分比時,觸發 AOF 重寫機制,默認值為 100 。
auto-aof-rewrite-min-size 參數表示當當前 AOF 文件大小超過指定值時,才可能觸發 AOF 重寫機制,默認值為 64 MB 。
系統自動觸發 AOF 重寫機制還需要滿足以下條件 :
當前沒有正在執行 BGSAVE 或 BGREWRITEAOF 的子進程
當前沒有正在執行 SAVE 的主進程
當前沒有正在進行集群切換或故障轉移
AOF 重寫機制可能遇到的問題
AOF 重寫機制可能會遇到內存不足或者內存碎片化的問題 。
內存不足是指當 fork 出子進程時,操作系統會為子進程分配和主進程相同大小的內存空間,如果主進程占用的內存過大,可能導致內存不足而 fork 失敗 。
內存碎片化是指當 fork 出子進程時,操作系統會使用寫時復制(copy-on-write)的技術,只有當主進程修改了內存頁時,才會為子進程復制一個新的內存頁 。但是如果主進程使用了大頁(huge page)的特性,那么每次復制的內存頁也會很大,可能導致內存碎片化而 fork 失敗 。
解決內存不足或者內存碎片化的問題的方法有以下幾種 :
增加物理內存或者虛擬內存
優化 Redis 的數據結構和編碼,減少內存占用
關閉大頁(huge page)的特性,避免復制過大的內存頁
優點:
- 備份機制更穩健,丟失數據概率更低。
- 可讀的日志文本,通過操作
AOF
文件,可以處理誤操作。
缺點:
- 比起
RDB
占用更多的磁盤空間。 - 恢復備份速度要慢。
- 每次讀寫都同步的話,有一定的性能壓力。
- 存在個別
Bug
,造成不能恢復。
2.2 Redis 7.x
2.2.1 Redis 6 AOF 中的
Redis 6
及之前的版本中的 AOF
機制,
1 內存開銷
由圖1可以看到,在AOFRW期間,主進程會將fork之后的數據變化寫進aof_rewrite_buf中,aof_rewrite_buf和aof_buf中的內容絕大部分都是重復的,因此這將帶來額外的內存冗余開銷。
在Redis INFO中的aof_rewrite_buffer_length字段可以看到當前時刻aof_rewrite_buf占用的內存大小。如下面顯示的,在高寫入流量下aof_rewrite_buffer_length幾乎和aof_buffer_length占用了同樣大的內存空間,幾乎浪費了一倍的內存。
aof_pending_rewrite:0
aof_buffer_length:35500
aof_rewrite_buffer_length:34000
aof_pending_bio_fsync:0
當aof_rewrite_buf占用的內存大小超過一定閾值時,我們將在Redis日志中看到如下信息。可以看到,aof_rewrite_buf占用了100MB的內存空間且主進程和子進程之間傳輸了2135MB的數據(子進程在通過pipe讀取這些數據時也會有內部讀buffer的內存開銷)。
對于內存型數據庫Redis而言,這是一筆不小的開銷。
3351:M 25 Jan 2022 09:55:39.655 * Background append only file rewriting started by pid 6817
3351:M 25 Jan 2022 09:57:51.864 * AOF rewrite child asks to stop sending diffs.
6817:C 25 Jan 2022 09:57:51.864 * Parent agreed to stop sending diffs. Finalizing AOF…
6817:C 25 Jan 2022 09:57:51.864 * Concatenating 2135.60 MB of AOF diff received from parent.
3351:M 25 Jan 2022 09:57:56.545 * Background AOF buffer size: 100 MB
AOFRW帶來的內存開銷有可能導致Redis內存突然達到maxmemory限制,從而影響正常命令的寫入,甚至會觸發操作系統限制被OOM Killer殺死,導致Redis不可服務。
2 CPU開銷
CPU的開銷主要有三個地方,分別解釋如下:
1、在AOFRW期間,主進程需要花費CPU時間向aof_rewrite_buf寫數據,并使用eventloop事件循環向子進程發送aof_rewrite_buf中的數據:
/* Append data to the AOF rewrite buffer, allocating new blocks if needed. */
void aofRewriteBufferAppend(unsigned char *s, unsigned long len) {
// 此處省略其他細節…
/* Install a file event to send data to the rewrite child if there is* not one already. */
if (!server.aof_stop_sending_diff &&aeGetFileEvents(server.el,server.aof_pipe_write_data_to_child) == 0)
{aeCreateFileEvent(server.el, server.aof_pipe_write_data_to_child,AE_WRITABLE, aofChildWriteDiffData, NULL);
} // 此處省略其他細節...
}
2、在子進程執行重寫操作的后期,會循環讀取pipe中主進程發送來的增量數據,然后追加寫入到臨時AOF文件:
int rewriteAppendOnlyFile(char *filename) {
// 此處省略其他細節…
/* Read again a few times to get more data from the parent.* We can't read forever (the server may receive data from clients* faster than it is able to send data to the child), so we try to read* some more data in a loop as soon as there is a good chance more data* will come. If it looks like we are wasting time, we abort (this* happens after 20 ms without new data). */
int nodata = 0;
mstime_t start = mstime();
while(mstime()-start < 1000 && nodata < 20) {if (aeWait(server.aof_pipe_read_data_from_parent, AE_READABLE, 1) <= 0){nodata++;continue;}nodata = 0; /* Start counting from zero, we stop on N *contiguous*timeouts. */aofReadDiffFromParent();
}// 此處省略其他細節...
}
3、在子進程完成重寫操作后,主進程會在backgroundRewriteDoneHandler 中進行收尾工作。其中一個任務就是將在重寫期間aof_rewrite_buf中沒有消費完成的數據寫入臨時AOF文件。如果aof_rewrite_buf中遺留的數據很多,這里也將消耗CPU時間。
void backgroundRewriteDoneHandler(int exitcode, int bysignal) {
// 此處省略其他細節…
/* Flush the differences accumulated by the parent to the rewritten AOF. */
if (aofRewriteBufferWrite(newfd) == -1) {serverLog(LL_WARNING,"Error trying to flush the parent diff to the rewritten AOF: %s", strerror(errno));close(newfd);goto cleanup;}// 此處省略其他細節...
}
AOFRW帶來的CPU開銷可能會造成Redis在執行命令時出現RT上的抖動,甚至造成客戶端超時的問題。
3 磁盤IO開銷
如前文所述,在AOFRW期間,主進程除了會將執行過的寫命令寫到aof_buf之外,還會寫一份到aof_rewrite_buf中。aof_buf中的數據最終會被寫入到當前使用的舊AOF文件中,產生磁盤IO。同時,aof_rewrite_buf中的數據也會被寫入重寫生成的新AOF文件中,產生磁盤IO。因此,同一份數據會產生兩次磁盤IO。
4 代碼復雜度
Redis使用下面所示的六個pipe進行主進程和子進程之間的數據傳輸和控制交互,這使得整個AOFRW邏輯變得更為復雜和難以理解。
/* AOF pipes used to communicate between parent and child during rewrite. */
int aof_pipe_write_data_to_child;
int aof_pipe_read_data_from_parent;
int aof_pipe_write_ack_to_parent;
int aof_pipe_read_ack_from_child;
int aof_pipe_write_ack_to_child;
int aof_pipe_read_ack_from_parent;
2.2.
2. 配置項
redis.conf
中 AOF
相關的配置如下:
############################## APPEND ONLY MODE ################################ By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check https://redis.io/topics/persistence for more information.appendonly no# The base name of the append only file.
#
# Redis 7 and newer use a set of append-only files to persist the dataset
# and changes applied to it. There are two basic types of files in use:
#
# - Base files, which are a snapshot representing the complete state of the
# dataset at the time the file was created. Base files can be either in
# the form of RDB (binary serialized) or AOF (textual commands).
# - Incremental files, which contain additional commands that were applied
# to the dataset following the previous file.
#
# In addition, manifest files are used to track the files and the order in
# which they were created and should be applied.
#
# Append-only file names are created by Redis following a specific pattern.
# The file name's prefix is based on the 'appendfilename' configuration
# parameter, followed by additional information about the sequence and type.
#
# For example, if appendfilename is set to appendonly.aof, the following file
# names could be derived:
#
# - appendonly.aof.1.base.rdb as a base file.
# - appendonly.aof.1.incr.aof, appendonly.aof.2.incr.aof as incremental files.
# - appendonly.aof.manifest as a manifest file.appendfilename "appendonly.aof"# For convenience, Redis stores all persistent append-only files in a dedicated
# directory. The name of the directory is determined by the appenddirname
# configuration parameter.appenddirname "appendonlydir"# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".# appendfsync always
appendfsync everysec
# appendfsync no# When the AOF fsync policy is set to always or everysec, and a background
# saving process (a background save or AOF log background rewriting) is
# performing a lot of I/O against the disk, in some Linux configurations
# Redis may block too long on the fsync() call. Note that there is no fix for
# this currently, as even performing fsync in a different thread will block
# our synchronous write(2) call.
#
# In order to mitigate this problem it's possible to use the following option
# that will prevent fsync() from being called in the main process while a
# BGSAVE or BGREWRITEAOF is in progress.
#
# This means that while another child is saving, the durability of Redis is
# the same as "appendfsync no". In practical terms, this means that it is
# possible to lose up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
#
# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.no-appendfsync-on-rewrite no# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb# An AOF file may be found to be truncated at the end during the Redis
# startup process, when the AOF data gets loaded back into memory.
# This may happen when the system where Redis is running
# crashes, especially when an ext4 filesystem is mounted without the
# data=ordered option (however this can't happen when Redis itself
# crashes or aborts but the operating system still works correctly).
#
# Redis can either exit with an error when this happens, or load as much
# data as possible (the default now) and start if the AOF file is found
# to be truncated at the end. The following option controls this behavior.
#
# If aof-load-truncated is set to yes, a truncated AOF file is loaded and
# the Redis server starts emitting a log to inform the user of the event.
# Otherwise if the option is set to no, the server aborts with an error
# and refuses to start. When the option is set to no, the user requires
# to fix the AOF file using the "redis-check-aof" utility before to restart
# the server.
#
# Note that if the AOF file will be found to be corrupted in the middle
# the server will still exit with an error. This option only applies when
# Redis will try to read more data from the AOF file but not enough bytes
# will be found.
aof-load-truncated yes# Redis can create append-only base files in either RDB or AOF formats. Using
# the RDB format is always faster and more efficient, and disabling it is only
# supported for backward compatibility purposes.
aof-use-rdb-preamble yes# Redis supports recording timestamp annotations in the AOF to support restoring
# the data from a specific point-in-time. However, using this capability changes
# the AOF format in a way that may not be compatible with existing AOF parsers.
aof-timestamp-enabled no
2.1 appendonly
appendonly
用于控制是否啟用AOF
持久化。
appendonly no
被設置為 no
(默認) 時,Redis
不會使用 AOF
持久化機制。
2.2 appendfilename
appendfilename
用于配置 AOF
文件的基礎名稱。
appendfilename "appendonly.aof"
Redis 7
及更高版本使用一組僅追加文件進行AOF
,文件主要有兩種類型:
- 基礎文件:是數據集在文件創建時完整狀態的快照。基礎文件可以是
RDB
(二進制序列化)格式或AOF
(文本命令)格式。 - 增量文件:包含在上一個文件之后對數據集應用的其他命令。
此外,還使用清單文件來跟蹤文件的創建順序,以及它們應該被應用的順序。
Redis
根據特定的模式創建AOF
文件的名稱。文件名的前綴基于appendfilename
配置參數,后面跟著關于序列和類型的額外信息。
例如,如果 appendfilename
被設置為appendonly.aof
,那么可能會產生以下文件名:
appendonly.aof.1.base.rdb
作為基礎文件。appendonly.aof.1.incr.aof
,appendonly.aof.2.incr.aof
作為增量文件。appendonly.aof.manifest
作為清單文件。
2.3 appenddirname
appenddirname
配置AOF
文件的存儲目錄。
appenddirname "appendonlydir"
2.4 appendfsync
appendfsync
用于配置AOF
緩沖區將操作同步(sync
)到磁盤的AOF
文件中的策略。
# appendfsync always
appendfsync everysec
# appendfsync no
fsync()
是一個系統調用,它告訴操作系統將數據實際寫入磁盤,而不是等待更多的數據進入輸出緩沖區。不同的操作系統對 fsync()
的實現可能有所不同,一些系統會立即將數據寫入磁盤,而另一些系統則會盡快嘗試這樣做。
Redis
支持三種不同的 fsync
模式:
no
:不進行fsync
調用,讓操作系統自行決定何時將數據刷新到磁盤。這種方式速度最快,但可能存在數據丟失的風險。always
:每次寫入AOF
日志后都進行fsync
調用。這是最慢但最安全的方式,因為每次寫入都會立即被刷新到磁盤。everysec
:每秒只進行一次fsync
調用。這是速度和數據安全性之間的一個折中方案。
默認值是 everysec
,因為它通常是在速度和數據安全性之間最好的折中方案。你可以根據自己的需求調整這個設置。如果你能接受一些數據丟失的風險并且追求更好的性能,可以考慮使用 no
模式(但請注意,如果你能接受數據丟失,那么默認的基于快照的持久化模式可能更合適)。相反,如果你追求更高的數據安全性,即使這意味著性能會降低,可以使用 always
模式。
2.5 no-appendfsync-on-rewrite
no-appendfsync-on-rewrite
用于配置在BGSAVE
或BGREWRITEAOF
正在進行時,是否阻止主進程調用fsync()
。
no-appendfsync-on-rewrite no
當AOF
的fsync
策略設置為always
或everysec
時,如果有一個后臺保存進程(后臺保存或AOF
日志后臺重寫)正在對磁盤進行大量I/O
操作,在某些Linux
配置下,Redis
可能會在fsync()
調用上阻塞過長時間。目前這個問題沒有修復方法,因為即使在不同的線程中執行fsync
也會阻塞我們的同步write
調用。
默認為no
,不阻止主進程fsync()
,還是會把數據往磁盤里刷,但是遇到重寫操作,可能會發生阻塞,數據安全,但是性能降低。
當設置為yes
時,在BGSAVE
或BGREWRITEAOF
正在進行時,主進程將不會執行fsync
調用。這意味著在這段時間內,Redis
的持久性與appendfsync no
設置時相同,即數據不會立即同步到磁盤。在最壞的情況下,你可能會丟失最多30
秒(使用默認Linux
設置)的AOF
日志數據。因此,如果你對延遲很敏感,可以將其設置為yes
。但是,從持久性的角度來看,將其保持為no
(默認值)是最安全的選擇。
2.6 auto-aof-rewrite-percentage、auto-aof-rewrite-min-size
AOF
采用文件追加方式,文件會越來越大為避免出現此種情況,新增了重寫機制,當AOF
文件的大小超過所設定的閾值時,Redis
會fork
出一條新進程來將文件重寫,也是先寫臨時文件最后再重命名。
重寫過程會創建一個新的 AOF
文件,其中只包含能夠恢復當前數據狀態所必需的最少命令,從而減小 AOF
文件的大小。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-percentage
用于設置一個百分比閾值,當 AOF
文件的大小相對于上一次重寫后的大小增長了超過這個百分比時,Redis
就會自動觸發 BGREWRITEAOF
命令來重寫 AOF
文件。設置為 100
(即 100%
),那么當 AOF
文件的大小增長了一倍時觸發重寫。
auto-aof-rewrite-min-size
用于設置一個 AOF
文件重寫所需的最小大小(以字節為單位)。只有當 AOF
文件的大小既超過了指定的百分比( auto-aof-rewrite-percentage
),又超過了 auto-aof-rewrite-min-size
指定的最小大小時,Redis
才會觸發 AOF
文件的重寫。
2.7 aof-load-truncated
aof-load-truncated
用于配置如果 AOF
文件末尾被截斷時的相關處理策略。
aof-load-truncated yes
在 Redis
啟動過程中,當 AOF
數據被加載回內存時,可能會發現 AOF
文件末尾被截斷。例如,在運行 Redis
的操作系統崩潰時,尤其是當 ext4
文件系統被掛載但沒有使用 data=ordered
選項。然而,當 Redis
本身崩潰或中止但操作系統仍然正常工作時,這種情況不會發生。
當發生這種情況時,Redis
可以選擇報錯退出,或者加載盡可能多的數據(現在是默認行為)并啟動,如果 AOF
文件末尾被截斷。以下選項控制這種行為。
aof-load-truncated yes
:會加載一個被截斷的AOF
文件,并且Redis
服務器會開始記錄日志以通知用戶該事件。aof-load-truncated no
:服務器會報錯并拒絕啟動。當選項設置為no
時,用戶需要使用 “redis-check-aof
” 工具修復AOF
文件后再重新啟動服務器。
2.8 aof-use-rdb-preamble
aof-use-rdb-preamble
用于配置是否使用 RDB
格式創建AOF
的基礎文件。使用 RDB
格式總是更快、更高效。
aof-use-rdb-preamble yes
2.9 aof-timestamp-enabled
aof-timestamp-enabled
用于配置 Redis
是否支持在 AOF
中記錄時間戳,以支持從特定時間點恢復數據。但是,使用這種功能會以可能與現有 AOF
解析器不兼容的方式更改 AOF
格式。
aof-timestamp-enabled no