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