溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis如何實(shí)現(xiàn)持久化

發(fā)布時(shí)間:2021-06-15 15:51:28 來源:億速云 閱讀:272 作者:chen 欄目:web開發(fā)

本篇內(nèi)容介紹了“Redis如何實(shí)現(xiàn)持久化”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Redis 的讀寫都是在內(nèi)存中進(jìn)行的,所以它的性能高。而當(dāng)我們的服務(wù)器斷開或者重啟的時(shí)候,數(shù)據(jù)就會(huì)消失,那么我們該怎么解決這個(gè)問題呢?

其實(shí) Redis 已經(jīng)為我們提供了一種持久化的機(jī)制,分別是 RDB 和 AOF  兩種方式,接下來跟著我一起看看這兩個(gè)錦囊都是怎么保證數(shù)據(jù)的持久化的。

持久化

由于 Redis 是基于內(nèi)存的數(shù)據(jù)庫,所以當(dāng)服務(wù)器出現(xiàn)故障的時(shí)候,我們的數(shù)據(jù)就得不到安全保障。

這個(gè)時(shí)候就需要將內(nèi)存中的數(shù)據(jù)存儲(chǔ)到磁盤中,當(dāng)我們服務(wù)器重啟時(shí),便可以通過磁盤來恢復(fù)數(shù)據(jù),這個(gè)過程就叫做 Redis 持久化。

Redis如何實(shí)現(xiàn)持久化

Redis持久化

RDB

簡介

RDB全稱Redis Database Backup file(Redis數(shù)據(jù)備份文件),也可以稱為Redis數(shù)據(jù)快照。

  • RDB 文件是一個(gè)經(jīng)過壓縮的二進(jìn)制文件(默認(rèn):dump.rdb);

  • RDB 文件保存在硬盤里;

  • 通過保存數(shù)據(jù)庫中的鍵值對來記錄數(shù)據(jù)庫狀態(tài)。

創(chuàng)建

當(dāng) Redis 持久化時(shí),程序會(huì)將當(dāng)前內(nèi)存中的數(shù)據(jù)庫狀態(tài)保存到磁盤中。

Redis如何實(shí)現(xiàn)持久化

創(chuàng)建

創(chuàng)建 RDB 文件主要有兩個(gè) Redis 命令:SAVE 和 BGSAVE。

SAVE

同步操作,執(zhí)行命令時(shí),會(huì)阻塞 Redis 服務(wù)器進(jìn)程,拒絕客戶端發(fā)送的命令請求。

代碼示例:

def SAVE():     # 創(chuàng)建 RDB 文件     rdbSave()

圖示:

Redis如何實(shí)現(xiàn)持久化

Save命令

BGSAVE

異步操作,執(zhí)行命令時(shí),子進(jìn)程執(zhí)行保存工作,服務(wù)器還可以繼續(xù)讓主線程處理客戶端發(fā)送的命令請求。

代碼示例:

def BGSAVE():     # 創(chuàng)建子進(jìn)程     pid = fork()      if pid == 0:         # 子進(jìn)程負(fù)責(zé)創(chuàng)建 RDB 文件         rdbSave()         # 完成之后向父進(jìn)程發(fā)送信號         signal_parent()     elif pid > 0:         # 父進(jìn)程繼續(xù)處理命令請求,并通過輪訓(xùn)等待子進(jìn)程的信號         handle_request_and_wait_signal()     else:         handle_fork_error()

圖示:

Redis如何實(shí)現(xiàn)持久化

bgSave命令

載入

載入工作在服務(wù)器啟動(dòng)時(shí)自動(dòng)執(zhí)行。

Redis如何實(shí)現(xiàn)持久化

載入

服務(wù)器在載入 RDB 文件期間,會(huì)一直處于阻塞狀態(tài),直到載入工作完成為止。

主要設(shè)置

Redis 允許用戶通過設(shè)置服務(wù)器配置的 save 選項(xiàng),讓服務(wù)器每隔一段時(shí)間自動(dòng)執(zhí)行一次 BGSAVE 命令。

設(shè)置保存條件

提供配置如下:

save 900 1 save 300 10

在這種情況下,只要滿足以下條件中的一個(gè),BGSAVE 命令就會(huì)被執(zhí)行:

  • 服務(wù)器在 900 秒之內(nèi),對數(shù)據(jù)庫進(jìn)行了至少 1 次修改了;

  • 服務(wù)器在 300 秒之內(nèi),對數(shù)據(jù)庫進(jìn)行了至少 10 次修改。

saveparams

服務(wù)器程序會(huì)根據(jù) save 選項(xiàng)所設(shè)置的保存條件,設(shè)置服務(wù)器狀態(tài) redisServer 結(jié)構(gòu)的 saveparams 屬性。

  • saveparams 屬性是一個(gè)數(shù)組;

  • 數(shù)組中的每一個(gè)元素都是一個(gè) saveparam 結(jié)構(gòu);

  • 每個(gè) saveparam 結(jié)構(gòu)都保存了一個(gè) save 選項(xiàng)設(shè)置的保存條件。

struct saveparam {     // 秒數(shù)     time_t seconds;     // 修改數(shù)     int changes; }

dirty

dirty 計(jì)數(shù)器記錄距離上一次成功執(zhí)行 SAVE 命令或 BGSAVE  命令之后,服務(wù)器對數(shù)據(jù)庫狀態(tài)進(jìn)行了多少次修改(包括寫入、刪除、更新等操作)。

lastsave

是一個(gè) UNINX 時(shí)間戳,記錄了服務(wù)器上一次成功執(zhí)行 SAVE 命令或者 BGSAVE 命令的時(shí)間。

檢查保存條件是否滿足

服務(wù)器周期性操作函數(shù) serverCron (該函數(shù)對正在運(yùn)行的服務(wù)器進(jìn)行維護(hù))默認(rèn)每隔 100 毫秒就會(huì)執(zhí)行一次,其中一項(xiàng)工作就是檢查 save  選項(xiàng)所設(shè)置的保存條件是否已經(jīng)滿足,滿足的話就執(zhí)行 BGSAVE 命令。

代碼示例:

def serverCron():     # ....     # 遍歷所有保存條件     for saveparam in server.saveparams:         # 計(jì)算距離上次執(zhí)行保存操作有多少秒         save_interval = unixtime_now() - server.lastsave          # 如果數(shù)據(jù)庫狀態(tài)的修改次數(shù)超過條件所設(shè)置的次數(shù)         # 如果距離上次保存的時(shí)間超過條件所設(shè)置的時(shí)間         if server.dirty >= saveparam.changes and save_interval > saveparam.seconds:             BGSAVE()

默認(rèn)配置

RDB 文件默認(rèn)的配置如下:

################################ SNAPSHOTTING  ################################ # # Save the DB on disk: #在給定的秒數(shù)和給定的對數(shù)據(jù)庫的寫操作數(shù)下,自動(dòng)持久化操作。 #   save <seconds> <changes> #  save 900 1 save 300 10 save 60 10000  #bgsave發(fā)生錯(cuò)誤時(shí)是否停止寫入,一般為yes stop-writes-on-bgsave-error yes  #持久化時(shí)是否使用LZF壓縮字符串對象? rdbcompression yes  #是否對rdb文件進(jìn)行校驗(yàn)和檢驗(yàn),通常為yes rdbchecksum yes  # RDB持久化文件名 dbfilename dump.rdb  #持久化文件存儲(chǔ)目錄 dir ./

AOF

簡介

AOF全稱為 Append Only File(追加日志文件)。日志是寫后日志,Redis 是先執(zhí)行命令,把數(shù)據(jù)寫入內(nèi)存,然后才記錄日志。

Redis如何實(shí)現(xiàn)持久化

寫后日志

  • 通過保存 Redis 服務(wù)器所執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài);

  • 寫入 AOF 文件的所有命令都是以 Redis 的命令請求協(xié)議格式保存的。

實(shí)現(xiàn)

AOF 持久化流程實(shí)現(xiàn)主要是通過以下流程來實(shí)現(xiàn)的:

Redis如何實(shí)現(xiàn)持久化

AOF流程

命令追加

若 AOF 持久化功能處于打開狀態(tài),服務(wù)器在執(zhí)行完一個(gè)命令后,會(huì)以協(xié)議格式將被執(zhí)行的寫命令追加到服務(wù)器狀態(tài)的 aof_buf 緩沖區(qū)的末尾。

文件同步

服務(wù)器每次結(jié)束一個(gè)事件循環(huán)之前,都會(huì)調(diào)用 flushAppendOnlyFile 函數(shù),這個(gè)函數(shù)會(huì)考慮是否需要將 aof_buf  緩沖區(qū)中的內(nèi)容寫入和保存到 AOF 文件里。

flushAppendOnlyFile 函數(shù)執(zhí)行以下流程:

  • WRITE:根據(jù)條件,將 aof_buf 中的緩存寫入到 AOF 文件;

  • SAVE:根據(jù)條件,調(diào)用 fsync 或 fdatasync 函數(shù),將 AOF 文件保存到磁盤中。

這個(gè)函數(shù)是由服務(wù)器配置的 appendfsync 的三個(gè)值:always、everysec、no來影響的,也被稱為三種策略。

Always

每條命令都會(huì) fsync 到硬盤中,這樣 redis 的寫入數(shù)據(jù)就不會(huì)丟失。

Redis如何實(shí)現(xiàn)持久化

Always

everysec

每秒都會(huì)刷新緩沖區(qū)到硬盤中(默認(rèn)值)。

Redis如何實(shí)現(xiàn)持久化

everysec

no

根據(jù)當(dāng)前操作系統(tǒng)的規(guī)則決定什么時(shí)候刷新到硬盤中,不需要我們來考慮。

Redis如何實(shí)現(xiàn)持久化

no

數(shù)據(jù)加載

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 創(chuàng)建一個(gè)不帶網(wǎng)絡(luò)連接的偽客戶端;

  3. 從 AOF 文件中分析并讀取出一條寫命令;

  4. 使用偽客戶端執(zhí)行被讀出的寫命令;

  5. 一直執(zhí)行步驟 2 和 3,直到 AOF 文件中的所有寫命令都被處理完畢為止。

文件重寫

為何需要文件重寫:

  • 為了解決 AOF 文件體積膨脹的問題;

  • 通過重寫創(chuàng)建一個(gè)新的 AOF 文件來替代現(xiàn)有的 AOF 文件,新的 AOF 文件不會(huì)包含任何浪費(fèi)空間的冗余命令。

實(shí)現(xiàn)

文件重寫的實(shí)現(xiàn)原理:

  • 不需要對現(xiàn)有的 AOF 文件進(jìn)行任何操作;

  • 從數(shù)據(jù)庫中直接讀取鍵現(xiàn)在的值;

  • 用一條命令記錄鍵值對,從而代替之前記錄這個(gè)鍵值對的多條命令。

后臺(tái)重寫

為不阻塞父進(jìn)程,Redis 將 AOF 重寫程序放到子進(jìn)程里執(zhí)行。

在子進(jìn)程執(zhí)行 AOF 重寫期間,服務(wù)器進(jìn)程需要執(zhí)行三個(gè)流程:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 執(zhí)行客戶端發(fā)來的命令;

  3. 將執(zhí)行后的寫命令追加到 AOF 緩沖區(qū);

  4. 將執(zhí)行后的寫命令追加到 AOF 重寫緩沖區(qū)。

Redis如何實(shí)現(xiàn)持久化

服務(wù)器流程

默認(rèn)配置

AOF 文件默認(rèn)的配置如下:

############################## APPEND ONLY MODE ###############################  #開啟AOF持久化方式 appendonly no  #AOF持久化文件名 appendfilename "appendonly.aof" #每秒把緩沖區(qū)的數(shù)據(jù)fsync到磁盤 appendfsync everysec # appendfsync no #是否在執(zhí)行重寫時(shí)不同步數(shù)據(jù)到AOF文件 no-appendfsync-on-rewrite no  # 觸發(fā)AOF文件執(zhí)行重寫的增長率 auto-aof-rewrite-percentage 100 #觸發(fā)AOF文件執(zhí)行重寫的最小size auto-aof-rewrite-min-size 64mb  #redis在恢復(fù)時(shí),會(huì)忽略最后一條可能存在問題的指令 aof-load-truncated yes  #是否打開混合開關(guān) aof-use-rdb-preamble yes

總結(jié)

通過以上的簡介,想必大家都對 Redis 持久化有了大致的了解,那么這兩種方式,我們該如何選擇呢?

  • 對于大中型的應(yīng)用,我們既想保證數(shù)據(jù)完整性又想保證高效率,就應(yīng)該結(jié)合使用 RDB 和 AOF 兩種方式;

  • 如果只是需要保證數(shù)據(jù)的完整性,保護(hù)數(shù)據(jù)不會(huì)丟失,那么優(yōu)先使用 AOF 方式;

  • 如果是處理大規(guī)模的數(shù)據(jù)恢復(fù),追求更高更快的效率的話,優(yōu)先使用 RDB 方式。

也可以參照下圖進(jìn)行選擇:

Redis如何實(shí)現(xiàn)持久化

“Redis如何實(shí)現(xiàn)持久化”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI