自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文讀懂 Redis RDB 持久化:策略、配置與應(yīng)用

開發(fā) Redis
本文將深入探討Redis RDB持久化,從它的基本概念、工作原理講起,詳細(xì)闡述其優(yōu)缺點、觸發(fā)機(jī)制、配置參數(shù)等關(guān)鍵內(nèi)容。

在Redis的世界里,數(shù)據(jù)的持久化猶如堅固的基石,支撐著整個系統(tǒng)的穩(wěn)定運(yùn)行與數(shù)據(jù)安全。在實際應(yīng)用場景中,我們不僅需要Redis強(qiáng)大的內(nèi)存處理能力,更需要確保數(shù)據(jù)在各種意外情況下不丟失,這時候持久化機(jī)制就顯得尤為重要。

Redis RDB(Redis Database)持久化作為Redis重要的持久化方式之一,有著獨特的魅力與價值。它以一種緊湊且高效的方式將Redis在某一時刻的數(shù)據(jù)快照保存到磁盤上,在Redis重啟時,可以快速地將這些數(shù)據(jù)恢復(fù)到內(nèi)存中,極大地提高了系統(tǒng)的可用性和數(shù)據(jù)恢復(fù)效率。

本文將深入探討Redis RDB持久化,從它的基本概念、工作原理講起,詳細(xì)闡述其優(yōu)缺點、觸發(fā)機(jī)制、配置參數(shù)等關(guān)鍵內(nèi)容。無論是初涉Redis的新手,還是想要深入理解持久化機(jī)制的開發(fā)者,都能從本文中收獲關(guān)于Redis RDB持久化的全面且深入的知識,為實際項目開發(fā)提供有力支持。

一、詳解RDB基礎(chǔ)

1. 什么是RDB

RDB持久化機(jī)制是將內(nèi)存中的數(shù)據(jù)生成快照并持久化到磁盤的過程,RDB可以通過手動或者自動的方式實現(xiàn)持久化:

2. RDB的幾種觸發(fā)時機(jī)

(1) 手動觸發(fā)

我們先來說說手動觸發(fā)即save命令,這個指令會直接阻塞當(dāng)前redis服務(wù)器,知道RDB完成了為止,對于線上生產(chǎn)環(huán)境數(shù)據(jù)的備份,我們非常非常不建議使用這種方式。

ounter(lineounter(lineounter(line
127.0.0.1:6379> save
OK

接下來就是bgsave指令了,bgsave則是主進(jìn)程fork一個子進(jìn)程,由子進(jìn)程完成持久化操作,而主進(jìn)程繼續(xù)處理客戶端的讀寫請求,如果我們需要手動實現(xiàn)持久化,非常推薦使用這種方式。

ounter(lineounter(lineounter(lineounter(line
# 從輸出我們就可以看出這種方式會將持久化的操作放在后臺執(zhí)行
127.0.0.1:6379> bgsave
Background saving started

(2) 被動觸發(fā)

還有一種就是被動觸發(fā),或者說是自動觸發(fā),自動觸發(fā)我們可以通過配置實現(xiàn)redis.conf的save參數(shù)實現(xiàn),如下所示,假如我們希望用戶20s內(nèi)寫入3次就進(jìn)行持久化,只需在配置中加一條save 20 3即可。

ounter(lineounter(line
save 20 3

需要注意的是save 20 3的20s是以redis的時間間隔為主,并不是用戶第1次寫入后的20s內(nèi)再寫入兩次進(jìn)行持久化,本質(zhì)上被動觸發(fā)是由redis server的一個定時任務(wù)掃描執(zhí)行:

(3) 關(guān)閉時持久化

當(dāng)我們執(zhí)行shutdown指令時,如果沒有明確指明參數(shù)nosave,該指令會調(diào)用rdbSave將當(dāng)前內(nèi)存中的鍵值對持久化到rdb文件中:

對應(yīng)我們也給出redis源碼中關(guān)于shutdown持久化的核心代碼,即位于db.c的shutdownCommand函數(shù):

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line




void shutdownCommand(redisClient *c) {
   	//......
   	//調(diào)用prepareForShutdown執(zhí)行rdb持久化
    if (prepareForShutdown(flags) == REDIS_OK) exit(0);
    addReplyError(c,"Errors trying to SHUTDOWN. Check logs.");
}




//服務(wù)器進(jìn)程關(guān)閉時調(diào)用rdbSave生成rdb文件
int prepareForShutdown(int flags) {
    int save = flags & REDIS_SHUTDOWN_SAVE;
    int nosave = flags & REDIS_SHUTDOWN_NOSAVE;


	 //......
    //如果存在rdb子進(jìn)程則殺掉
    if (server.rdb_child_pid != -1) {
        redisLog(REDIS_WARNING,"There is a child saving an .rdb. Killing it!");
        kill(server.rdb_child_pid,SIGUSR1);
        rdbRemoveTempFile(server.rdb_child_pid);
    }
  	//......
    /**
     * 符合以下任意條件都會觸發(fā)rdb持久化:
     * 1. 如果我們有配置save參數(shù)例如(save 20 3) 則saveparamslen大于0,且nosave非0
     * 2. save為1(默認(rèn)情況下會指明1)
     */
    if ((server.saveparamslen > 0 && !nosave) || save) {      
        //執(zhí)行rdb持久化
        if (rdbSave(server.rdb_filename) != REDIS_OK) {
          //......
            return REDIS_ERR;
        }
    }
    //......
    return REDIS_OK;
}

3. RDB的使用方式

基于上述配置我們簡單演示一下RDB持久化機(jī)制,我們首先需要存點數(shù)據(jù),20s存3個值:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK

完成后查看是否生成rdb文件,確認(rèn)無誤后,我們將這個文件備份,并強(qiáng)制關(guān)閉redis服務(wù)端,模擬斷電的場景:

ounter(lineounter(lineounter(line


# 重命名rdb文件
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# mv dump.rdb dump.rdb.bak

此時我們再啟動redis就會發(fā)現(xiàn)數(shù)據(jù)為空:

ounter(lineounter(line
127.0.0.1:6379> keys *
(empty array)

我們將rdb文件還原,并重啟redis,可以發(fā)現(xiàn)備份數(shù)據(jù)還原了:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
# 強(qiáng)制關(guān)閉redis
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# ps -ef |grep redis |grep -v grep
root      8956     1  0 23:22 ?        00:00:00 redis-server 127.0.0.1:6379
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# kill -9 8956


# 還原rdb,并啟動redis
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# mv dump.rdb.bak dump.rdb
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-server /root/redis/redis.conf
[root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli


# 可以看到之前設(shè)置的數(shù)據(jù)都回來了
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"

4. 詳解bgsave的工作流程

bgsave的工作流程如下圖所示,整體可以簡述為:

  • 主進(jìn)程fork出一個子進(jìn)程,這時候主進(jìn)程會被阻塞。
  • 子進(jìn)程創(chuàng)建完成后,redis客戶端會輸出Background saving started,這就意味子進(jìn)程開始進(jìn)行持久化操作了。
  • 子進(jìn)程持久化完成后,會生成一個rdb文件,將本次的rdb文件通過原子替換的方式將上一次備份的rdb覆蓋。
  • 子進(jìn)程發(fā)送信號通知父進(jìn)程本次任務(wù)完成。

5. RDB常見的配置參數(shù)(了解)

首先是dbfilename ,它可以指定rdb的文件名:

ounter(lineounter(lineounter(lineounter(line


# The filename where to dump the DB
dbfilename dump.rdb

接下來就是dir,它可以指定rdb文件的持久化的位置,默認(rèn)取redis服務(wù)端的位置。

ounter(lineounter(linedir ./
ounter(lineounter(line
dir ./

當(dāng)reids無法將文件寫入磁盤,我們可以講stop-writes-on-bgsave-error設(shè)置為yes,直接關(guān)掉redis的寫操作,默認(rèn)為yes:

ounter(lineounter(lineounter(line


stop-writes-on-bgsave-error yes

rdbcompression 開啟后,redis默認(rèn)會通過LZF算法壓縮rdb文件。這種方式會消耗CPU,但是壓縮后的大小遠(yuǎn)遠(yuǎn)小于內(nèi)存,但是帶來的收益卻遠(yuǎn)遠(yuǎn)大于這點開銷,通過壓縮的文件無論是通過網(wǎng)絡(luò)發(fā)送到從節(jié)點還是存儲到硬盤的空間都是非??捎^的。

ounter(lineounter(lineounter(lineounter(line




rdbcompression yes

rdbchecksum 開啟后,在存儲快照后,還可以讓redis使用CRC64算法來進(jìn)行數(shù)據(jù)校驗,但是這樣做會增加大約10%的性能消耗,如果希望獲取到最大的性能提升,可以關(guān)閉此功能。

ounter(lineounter(line
rdbchecksum yes

6. RDB有哪些優(yōu)缺點

優(yōu)點:

  • rdb是緊湊壓縮的二進(jìn)制文件,非常實用與備份或者全景復(fù)制等場景。
  • rdb恢復(fù)數(shù)據(jù)效率遠(yuǎn)遠(yuǎn)高于aof

而缺點如下:

  • 無法做到毫秒級別的實時性持久化,盡管我們可以通過設(shè)置緊湊的save完成持久化,但是頻繁的fork子進(jìn)程進(jìn)行持久化,很可能造成redis主進(jìn)行長期阻塞。

  • 存儲的文件是二進(jìn)制,不夠直觀,可能還存在某些兼容問題。

二、詳解RDB進(jìn)階知識點

1. 我們?yōu)镽edis開辟的一塊大內(nèi)存空間,進(jìn)行持久化時就可能耗時長,這段時間還可能收到客戶端的請求,如何保持持久化后的數(shù)據(jù)一致性?

在進(jìn)行周期性快照數(shù)據(jù)持久化期間,redis會fork一個子進(jìn)程異步執(zhí)行,但是父子進(jìn)程仍然共享同一個代碼段和數(shù)據(jù)段,兩者并行操作存在線程安全的風(fēng)險。

所以在快照持久化期間,主進(jìn)程的修改操作都采用了寫時復(fù)制(Copy On Write)的思想,即將需要進(jìn)行操作的鍵值對數(shù)據(jù)從原有數(shù)據(jù)頁中復(fù)制出一份副本進(jìn)行修改,等到bgsave子進(jìn)程快照完成后,再將這塊內(nèi)存區(qū)域同步到原來的內(nèi)存區(qū)域中,等待下一次快照:

這樣做的缺點也很明顯,極端情況下,如果在bgsave期間主進(jìn)程數(shù)據(jù)都被改了,那么內(nèi)存占用就是原來的兩倍:

2. 在進(jìn)行快照操作的這段時間,如果發(fā)生服務(wù)崩潰怎么辦?

服務(wù)恢復(fù)的數(shù)據(jù)只會是上一次備份的rdb文件數(shù)據(jù),因為bgsave子進(jìn)程只會將操作成功的文件生成rdb文件覆蓋上一次備份的文件。

3. 可以每秒做一次快照嗎?

可能會有下面這幾個問題:

  • 頻繁寫入內(nèi)存數(shù)據(jù)會給磁盤帶來很大的壓力,多個fork子進(jìn)程搶占優(yōu)先的磁盤帶寬,前一個子進(jìn)程沒寫完,后一個子進(jìn)程又來寫入。
  • 雖說快照這個操作是單位時間內(nèi)只能執(zhí)行一次異步,但是不間斷的rdb異步持久化每次fork子進(jìn)程這個操作都會阻塞主進(jìn)程,頻繁fork很可能對于性能開銷還是很大的。
  • 對于全量大數(shù)據(jù)快照操作是很耗時的,即使我們延長了RDB快照的調(diào)度間隔,redis每次進(jìn)行rdb持久化之前也會檢查當(dāng)前是否有子進(jìn)程執(zhí)行快照,如果存在則不允許快照,所以針對數(shù)據(jù)量較大的場景做這種頻繁保存的操作意義也不大。

對應(yīng)筆者也給出的bgsave的源碼實現(xiàn),可以看到在每次進(jìn)行持久化的時候bgsaveCommand都會檢查當(dāng)前是否有子進(jìn)程正在執(zhí)行RDB持久化,如果存在則不允許用戶進(jìn)行持久化:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
//調(diào)用rdbSaveBackground創(chuàng)建一個子進(jìn)程生成rdb文件,不影響主線程
void bgsaveCommand(redisClient *c) {
	//如果存在rdb或者aof的子進(jìn)程則直接不允許執(zhí)行bgsave
    if (server.rdb_child_pid != -1) {
        addReplyError(c,"Background save already in progress");
    } else if (server.aof_child_pid != -1) {
        addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");
    } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {
        addReplyStatus(c,"Background saving started");
    } else {
        addReply(c,shared.err);
    }
}
責(zé)任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關(guān)推薦

2024-12-20 12:15:06

RedisRDB持久化

2020-12-11 11:40:37

RDBAOFRedis

2023-12-26 07:33:45

Redis持久化COW

2024-01-03 08:54:17

Kubernetes策略工具

2023-11-21 09:41:00

緩存策略存儲

2021-07-18 07:59:42

RedisRDBAOF

2024-03-26 00:03:08

Redis數(shù)據(jù)RDB

2021-09-04 19:04:14

配置LogbackJava

2022-05-12 08:01:18

KubernetesDocker容器

2022-02-15 08:07:17

測試軟件開發(fā)

2017-06-02 15:32:09

大數(shù)據(jù)數(shù)據(jù)可視化

2021-05-28 10:25:39

Redis數(shù)據(jù)庫內(nèi)存

2022-03-13 18:27:09

Redis數(shù)據(jù)庫開源

2021-03-30 18:05:10

數(shù)字化轉(zhuǎn)型計算機(jī)技術(shù)

2024-09-29 09:25:53

2023-05-11 09:12:35

RedisRDB日志

2024-09-12 08:49:53

2023-12-22 19:59:15

2021-08-04 16:06:45

DataOps智領(lǐng)云

2024-03-20 10:31:27

點贊
收藏

51CTO技術(shù)棧公眾號