redis AOF儲存機制

來源:互聯網
上載者:User

標籤:

網上說AOF有三種儲存方式,不自動儲存、每秒自動儲存、每命令自動儲存。

其中每秒自動儲存這個看起來很美好,但是可能會被各種IO的時間所延遲,所以究竟是怎麼判斷每秒儲存的,並不是太明白,故有此文。

AOF 命令同步

Redis 將所有對資料庫進行過寫入的命令(及其參數)記錄到 AOF 檔案, 以此達到記錄資料庫狀態的目的, 為了方便起見, 我們稱呼這種記錄過程為同步。

舉個例子, 如果執行以下命令:

redis> RPUSH list 1 2 3 4(integer) 4redis> LRANGE list 0 -11) "1"2) "2"3) "3"4) "4"redis> KEYS *1) "list"redis> RPOP list"4"redis> LPOP list"1"redis> LPUSH list 1(integer) 3redis> LRANGE list 0 -11) "1"2) "2"3) "3"

 

那麼其中四條對資料庫有修改的寫入命令就會被同步到 AOF 檔案中:

RPUSH list 1 2 3 4RPOP listLPOP listLPUSH list 1

 

為了處理的方便, AOF 檔案使用網路通訊協議的格式來儲存這些命令。

比如說, 上面列舉的四個命令在 AOF 檔案中就實際儲存如下:

*2$6SELECT$10*6$5RPUSH$4list$11$12$13$14*2$4RPOP$4list*2$4LPOP$4list*3$5LPUSH$4list$11

 

除了select命令是 AOF 程式自己加上去的之外, 其他命令都是之前我們在終端裡執行的命令。

同步命令到 AOF 檔案的整個過程可以分為三個階段:

  1. 命令傳播:Redis 將執行完的命令、命令的參數、命令的參數個數等資訊發送到 AOF 程式中。
  2. 緩衝追加:AOF 程式根據接收到的命令資料,將命令轉換為網路通訊協議的格式,然後將協議內容追加到伺服器的 AOF 緩衝中。
  3. 檔案寫入和儲存:AOF 緩衝中的內容被寫入到 AOF 檔案末尾,如果設定的 AOF 儲存條件被滿足的話, fsync 函數或者 fdatasync 函數會被調用,將寫入的內容真正地儲存到磁碟中。

以下幾個小節將詳細地介紹這三個步驟。

命令傳播

當一個 Redis 用戶端需要執行命令時, 它通過網路連接, 將協議文本發送給 Redis 伺服器。

比如說, 要執行命令 SET KEY VALUE , 用戶端將向伺服器發送文本 "*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n" 。

伺服器在接到用戶端的請求之後, 它會根據協議文本的內容, 選擇適當的命令函數, 並將各個參數從字串文本轉換為 Redis 字串對象(StringObject)。

比如說, 針對上面的 SET 命令例子, Redis 將用戶端的命令指標指向實現 SET 命令的 setCommand 函數, 並建立三個 Redis 字串對象, 分別儲存 SET 、 KEY 和 VALUE 三個參數(命令也算作參數)。

每當命令函數成功執行之後, 命令參數都會被傳播到 AOF 程式, 以及 REPLICATION 程式(本節不討論這個,列在這裡只是為了完整性的考慮)。

這個執行並傳播命令的過程可以用以下虛擬碼表示:

if (execRedisCommand(cmd, argv, argc) == EXEC_SUCCESS):    if aof_is_turn_on():        # 傳播命令到 AOF 程式        propagate_aof(cmd, argv, argc)    if replication_is_turn_on():        # 傳播命令到 REPLICATION 程式        propagate_replication(cmd, argv, argc)

以下是該過程的流程圖:

緩衝追加

當命令被傳播到 AOF 程式之後, 程式會根據命令以及命令的參數, 將命令從字串對象轉換回原來的協議文本。

比如說, 如果 AOF 程式接受到的三個參數分別儲存著 SET 、 KEY 和 VALUE 三個字串, 那麼它將產生協議文本"*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n" 。

協議文本產生之後, 它會被追加到 redis.h/redisServer 結構的 aof_buf 末尾。

redisServer 結構維持著 Redis 伺服器的狀態, aof_buf 域則儲存著所有等待寫入到 AOF 檔案的協議文本:

struct redisServer {    // 其他域...    sds aof_buf;    // 其他域...};

至此, 追加命令到緩衝的步驟執行完畢。

綜合起來,整個緩衝追加過程可以分為以下三步:

  1. 接受命令、命令的參數、以及參數的個數、所使用的資料庫等資訊。
  2. 將命令還原成 Redis 網路通訊協議。
  3. 將協議文本追加到 aof_buf 末尾。
檔案寫入和儲存

每當伺服器常規任務函數被執行、 或者事件處理器被執行時, aof.c/flushAppendOnlyFile 函數都會被調用, 這個函數執行以下兩個工作:

WRITE:根據條件,將 aof_buf 中的緩衝寫入到 AOF 檔案。

SAVE:根據條件,調用 fsync 或 fdatasync 函數,將 AOF 檔案儲存到磁碟中。

兩個步驟都需要根據一定的條件來執行, 而這些條件由 AOF 所使用的儲存模式來決定, 以下小節就來介紹 AOF 所使用的三種儲存模式, 以及在這些模式下, 步驟 WRITE 和 SAVE 的調用條件。

AOF 儲存模式

Redis 目前支援三種 AOF 儲存模式,它們分別是:

  1. AOF_FSYNC_NO :不儲存。
  2. AOF_FSYNC_EVERYSEC :每一秒鐘儲存一次。
  3. AOF_FSYNC_ALWAYS :每執行一個命令儲存一次。

以下三個小節將分別討論這三種儲存模式。

不儲存

在這種模式下, 每次調用 flushAppendOnlyFile 函數, WRITE 都會被執行, 但 SAVE 會被略過。

在這種模式下, SAVE 只會在以下任意一種情況中被執行:

  • Redis 被關閉
  • AOF 功能被關閉
  • 系統的寫緩衝被重新整理(可能是緩衝已經被寫滿,或者定期儲存操作被執行)

這三種情況下的 SAVE 操作都會引起 Redis 主進程阻塞。

每一秒鐘儲存一次

在這種模式中, SAVE 原則上每隔一秒鐘就會執行一次, 因為 SAVE 操作是由後檯子線程調用的, 所以它不會引起伺服器主進程阻塞。

注意, 在上一句的說明裡面使用了詞語“原則上”, 在實際運行中, 程式在這種模式下對 fsync 或 fdatasync 的調用並不是每秒一次, 它和調用 flushAppendOnlyFile 函數時 Redis 所處的狀態有關。

每當 flushAppendOnlyFile 函數被調用時, 可能會出現以下四種情況:

  • 子線程正在執行 SAVE ,並且:

    1. 這個 SAVE 的執行時間未超過 2 秒,那麼程式直接返回,並不執行 WRITE 或新的 SAVE 。
    2. 這個 SAVE 已經執行超過 2 秒,那麼程式執行 WRITE ,但不執行新的 SAVE 。注意,因為這時 WRITE 的寫入必須等待子線程先完成(舊的) SAVE ,因此這裡 WRITE 會比平時阻塞更長時間。
  • 子線程沒有在執行 SAVE ,並且:

    1. 上次成功執行 SAVE 距今不超過 1 秒,那麼程式執行 WRITE ,但不執行 SAVE 。
    2. 上次成功執行 SAVE 距今已經超過 1 秒,那麼程式執行 WRITE 和 SAVE 。

可以用流程圖表示這四種情況:

根據以上說明可以知道, 在“每一秒鐘儲存一次”模式下, 如果在情況 1 中發生故障停機, 那麼使用者最多損失小於 2 秒內所產生的所有資料。

如果在情況 2 中發生故障停機, 那麼使用者損失的資料是可以超過 2 秒的。

Redis 官網上所說的, AOF 在“每一秒鐘儲存一次”時發生故障, 只丟失 1 秒鐘資料的說法, 實際上並不準確。

每執行一個命令儲存一次

在這種模式下,每次執行完一個命令之後, WRITE 和 SAVE 都會被執行。

另外,因為 SAVE 是由 Redis 主進程執行的,所以在 SAVE 執行期間,主進程會被阻塞,不能接受命令請求。

AOF 儲存模式對效能和安全性的影響

在上一個小節, 我們簡短地描述了三種 AOF 儲存模式的工作方式, 現在, 是時候研究一下這三個模式在安全性和效能方面的區別了。

對於三種 AOF 儲存模式, 它們對伺服器主進程的阻塞情況如下:

  1. 不儲存(AOF_FSYNC_NO):寫入和儲存都由主進程執行,兩個操作都會阻塞主進程。
  2. 每一秒鐘儲存一次(AOF_FSYNC_EVERYSEC):寫入操作由主進程執行,阻塞主進程。儲存操作由子線程執行,不直接阻塞主進程,但儲存操作完成的快慢會影響寫入操作的阻塞時間長度。
  3. 每執行一個命令儲存一次(AOF_FSYNC_ALWAYS):和模式 1 一樣。

因為阻塞操作會讓 Redis 主進程無法持續處理請求, 所以一般說來, 阻塞操作執行得越少、完成得越快, Redis 的效能就越好。

模式 1 的儲存操作只會在AOF 關閉或 Redis 關閉時執行, 或者由作業系統觸發, 在一般情況下, 這種模式只需要為寫入阻塞, 因此它的寫入效能要比後面兩種模式要高, 當然, 這種效能的提高是以降低安全性為代價的: 在這種模式下, 如果啟動並執行中途發生停機, 那麼遺失資料的數量由作業系統的緩衝沖洗策略決定。

模式 2 在效能方面要優於模式 3 , 並且在通常情況下, 這種模式最多丟失不多於 2 秒的資料, 所以它的安全性要高於模式 1 , 這是一種兼顧效能和安全性的儲存方案。

模式 3 的安全性是最高的, 但效能也是最差的, 因為伺服器必須阻塞直到命令資訊被寫入並儲存到磁碟之後, 才能繼續處理請求。

綜合起來,三種 AOF 模式的操作特性可以總結如下:

模式 WRITE 是否阻塞? SAVE 是否阻塞? 停機時丟失的資料量
AOF_FSYNC_NO 阻塞 阻塞 作業系統最後一次對 AOF 檔案觸發 SAVE 操作之後的資料。
AOF_FSYNC_EVERYSEC 阻塞 不阻塞 一般情況下不超過 2 秒鐘的資料。
AOF_FSYNC_ALWAYS 阻塞 阻塞 最多隻丟失一個命令的資料。

redis AOF儲存機制

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.