W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
AOF 持久化功能的實現(xiàn)可以分為命令追加(append)、文件寫入、文件同步(sync)三個步驟。
當 AOF 持久化功能處于打開狀態(tài)時, 服務(wù)器在執(zhí)行完一個寫命令之后, 會以協(xié)議格式將被執(zhí)行的寫命令追加到服務(wù)器狀態(tài)的 aof_buf
緩沖區(qū)的末尾:
struct redisServer {
// ...
// AOF 緩沖區(qū)
sds aof_buf;
// ...
};
舉個例子, 如果客戶端向服務(wù)器發(fā)送以下命令:
redis> SET KEY VALUE
OK
那么服務(wù)器在執(zhí)行這個 SET 命令之后, 會將以下協(xié)議內(nèi)容追加到 aof_buf
緩沖區(qū)的末尾:
*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\n
又比如說, 如果客戶端向服務(wù)器發(fā)送以下命令:
redis> RPUSH NUMBERS ONE TWO THREE
(integer) 3
那么服務(wù)器在執(zhí)行這個 RPUSH 命令之后, 會將以下協(xié)議內(nèi)容追加到 aof_buf
緩沖區(qū)的末尾:
*5\r\n$5\r\nRPUSH\r\n$7\r\nNUMBERS\r\n$3\r\nONE\r\n$3\r\nTWO\r\n$5\r\nTHREE\r\n
以上就是 AOF 持久化的命令追加步驟的實現(xiàn)原理。
Redis 的服務(wù)器進程就是一個事件循環(huán)(loop), 這個循環(huán)中的文件事件負責(zé)接收客戶端的命令請求, 以及向客戶端發(fā)送命令回復(fù), 而時間事件則負責(zé)執(zhí)行像 serverCron
函數(shù)這樣需要定時運行的函數(shù)。
因為服務(wù)器在處理文件事件時可能會執(zhí)行寫命令, 使得一些內(nèi)容被追加到 aof_buf
緩沖區(qū)里面, 所以在服務(wù)器每次結(jié)束一個事件循環(huán)之前, 它都會調(diào)用 flushAppendOnlyFile
函數(shù), 考慮是否需要將 aof_buf
緩沖區(qū)中的內(nèi)容寫入和保存到 AOF 文件里面, 這個過程可以用以下偽代碼表示:
def eventLoop():
while True:
# 處理文件事件,接收命令請求以及發(fā)送命令回復(fù)
# 處理命令請求時可能會有新內(nèi)容被追加到 aof_buf 緩沖區(qū)中
processFileEvents()
# 處理時間事件
processTimeEvents()
# 考慮是否要將 aof_buf 中的內(nèi)容寫入和保存到 AOF 文件里面
flushAppendOnlyFile()
flushAppendOnlyFile
函數(shù)的行為由服務(wù)器配置的 appendfsync
選項的值來決定, 各個不同值產(chǎn)生的行為如表 TABLE_APPENDFSYNC 所示。
appendfsync 選項的值 |
flushAppendOnlyFile 函數(shù)的行為 |
---|---|
always |
將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入并同步到 AOF 文件。 |
everysec |
將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 如果上次同步 AOF 文件的時間距離現(xiàn)在超過一秒鐘, 那么再次對 AOF 文件進行同步, 并且這個同步操作是由一個線程專門負責(zé)執(zhí)行的。 |
no |
將 aof_buf 緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 但并不對 AOF 文件進行同步, 何時同步由操作系統(tǒng)來決定。 |
如果用戶沒有主動為 appendfsync
選項設(shè)置值, 那么 appendfsync
選項的默認值為 everysec
, 關(guān)于 appendfsync
選項的更多信息, 請參考 Redis 項目附帶的示例配置文件 redis.conf
。
文件的寫入和同步
為了提高文件的寫入效率, 在現(xiàn)代操作系統(tǒng)中, 當用戶調(diào)用 write
函數(shù), 將一些數(shù)據(jù)寫入到文件的時候, 操作系統(tǒng)通常會將寫入數(shù)據(jù)暫時保存在一個內(nèi)存緩沖區(qū)里面, 等到緩沖區(qū)的空間被填滿、或者超過了指定的時限之后, 才真正地將緩沖區(qū)中的數(shù)據(jù)寫入到磁盤里面。
這種做法雖然提高了效率, 但也為寫入數(shù)據(jù)帶來了安全問題, 因為如果計算機發(fā)生停機, 那么保存在內(nèi)存緩沖區(qū)里面的寫入數(shù)據(jù)將會丟失。
為此, 系統(tǒng)提供了 fsync
和 fdatasync
兩個同步函數(shù), 它們可以強制讓操作系統(tǒng)立即將緩沖區(qū)中的數(shù)據(jù)寫入到硬盤里面, 從而確保寫入數(shù)據(jù)的安全性。
舉個例子, 假設(shè)服務(wù)器在處理文件事件期間, 執(zhí)行了以下三個寫入命令:
SADD databases "Redis" "MongoDB" "MariaDB"
SET date "2013-9-5"
INCR click_counter 10086
那么 aof_buf
緩沖區(qū)將包含這三個命令的協(xié)議內(nèi)容:
*5\r\n$4\r\nSADD\r\n$9\r\ndatabases\r\n$5\r\nRedis\r\n$7\r\nMongoDB\r\n$7\r\nMariaDB\r\n
*3\r\n$3\r\nSET\r\n$4\r\ndate\r\n$8\r\n2013-9-5\r\n
*3\r\n$4\r\nINCR\r\n$13\r\nclick_counter\r\n$5\r\n10086\r\n
如果這時 flushAppendOnlyFile
函數(shù)被調(diào)用, 假設(shè)服務(wù)器當前 appendfsync
選項的值為 everysec
, 并且根據(jù) server.aof_last_fsync
屬性顯示, 距離上次同步 AOF 文件已經(jīng)超過一秒鐘, 那么服務(wù)器會先將 aof_buf
中的內(nèi)容寫入到 AOF 文件中, 然后再對 AOF 文件進行同步。
以上就是對 AOF 持久化功能的文件寫入和文件同步這兩個步驟的介紹。
AOF 持久化的效率和安全性
服務(wù)器配置 appendfsync
選項的值直接決定 AOF 持久化功能的效率和安全性。
當 appendfsync
的值為 always
時, 服務(wù)器在每個事件循環(huán)都要將 aof_buf
緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 并且同步 AOF 文件, 所以 always
的效率是 appendfsync
選項三個值當中最慢的一個, 但從安全性來說, always
也是最安全的, 因為即使出現(xiàn)故障停機, AOF 持久化也只會丟失一個事件循環(huán)中所產(chǎn)生的命令數(shù)據(jù)。
當 appendfsync
的值為 everysec
時, 服務(wù)器在每個事件循環(huán)都要將 aof_buf
緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 并且每隔超過一秒就要在子線程中對 AOF 文件進行一次同步: 從效率上來講, everysec
模式足夠快, 并且就算出現(xiàn)故障停機, 數(shù)據(jù)庫也只丟失一秒鐘的命令數(shù)據(jù)。
當 appendfsync
的值為 no
時, 服務(wù)器在每個事件循環(huán)都要將 aof_buf
緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 至于何時對 AOF 文件進行同步, 則由操作系統(tǒng)控制。
因為處于 no
模式下的 flushAppendOnlyFile
調(diào)用無須執(zhí)行同步操作, 所以該模式下的 AOF 文件寫入速度總是最快的, 不過因為這種模式會在系統(tǒng)緩存中積累一段時間的寫入數(shù)據(jù), 所以該模式的單次同步時長通常是三種模式中時間最長的: 從平攤操作的角度來看, no
模式和 everysec
模式的效率類似, 當出現(xiàn)故障停機時, 使用 no
模式的服務(wù)器將丟失上次同步 AOF 文件之后的所有寫命令數(shù)據(jù)。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: