京東網(wǎng)站建設(shè)步驟關(guān)鍵詞排名關(guān)鍵詞快速排名
文章目錄
- Redis 持久化
- 1 持久化基本原理
- 2 RDB(Redis DataBase) 持久化
- 2.1 持久化的執(zhí)行
- 2.2 手動(dòng) save 命令
- 2.3 手動(dòng) bgsave 命令
- 2.4 自動(dòng)條件觸發(fā)
- 2.5 查看持久化時(shí)間
- 3 RDB 優(yōu)化配置
- 3.1 save
- 3.2 stop-write-on-bgsave-error
- 3.3 rdbcompression
- 3.4 rdbchecksum
- 3.5 sanitize-dump-payload
- 3.6 dbfilename
- 3.7 rdb-del-sync-files
- 3.8 dir
- 4 RDB 文件結(jié)構(gòu)
- 5 RDB 持久化過(guò)程
- 6 補(bǔ)充寫(xiě)實(shí)復(fù)制技術(shù)
Redis 持久化
- Redis 是一個(gè)內(nèi)存數(shù)據(jù)庫(kù),所以其運(yùn)行效率非常高。但是存在一個(gè)問(wèn)題:內(nèi)存中的數(shù)據(jù)是不持久的,若主機(jī)宕機(jī)或 Redis 關(guān)機(jī)重啟,則內(nèi)存中的數(shù)據(jù)全部丟失。Redis 具有持久化功能,其會(huì)按照設(shè)置以快照或操作日志的形式將數(shù)據(jù)持久化到磁盤。
- 根據(jù)持久化使用技術(shù)的不同,Redis 的持久化分為兩種:RDB 與 AOF
1 持久化基本原理

- Redis 持久化稱為鈍化,是指將內(nèi)存中數(shù)據(jù)庫(kù)的狀態(tài)描述信息保存到磁盤中。不同的持久化技術(shù),對(duì)數(shù)據(jù)的狀態(tài)描述信息是不同的,生成的持久化文件也是不同的。但作用都是相同的:避免數(shù)據(jù)意外丟失。
- 數(shù)據(jù)恢復(fù)過(guò)程也稱為激活。通過(guò)手動(dòng)方式,或自動(dòng)定時(shí)方式,或自動(dòng)條件觸發(fā)方式,將內(nèi)存中數(shù)據(jù)庫(kù)的狀態(tài)描述信息寫(xiě)入到指定的持久化文件中。當(dāng)系統(tǒng)重新啟動(dòng)時(shí),自動(dòng)加載持久化文件,并根據(jù)文件中數(shù)據(jù)庫(kù)狀態(tài)描述信息將數(shù)據(jù)恢復(fù)到內(nèi)存中。
- 鈍化與激活的過(guò)程就是 Redis 持久化的基本原理。
- 對(duì)于 Redis 單機(jī)狀態(tài)下,無(wú)論是手動(dòng)方式,還是定時(shí)方式或條件觸發(fā)方式,都存在數(shù)據(jù)丟失問(wèn)題:在尚未手動(dòng)/自動(dòng)保存時(shí)發(fā)生了 Redis 宕機(jī)狀況,那么從上次保存到宕機(jī)期間產(chǎn)生的數(shù)據(jù)就會(huì)丟失。不同的持久化方式,其數(shù)據(jù)的丟失率也是不同
- RDB 是默認(rèn)持久化方式,但 Redis 允許 RDB 與 AOF 兩種持久化技術(shù)同時(shí)開(kāi)啟,此時(shí)系統(tǒng)會(huì)使用 AOF 方式做持久化,即 AOF 持久化技術(shù)的優(yōu)先級(jí)要更高。同樣兩種技術(shù)同時(shí)開(kāi)啟狀態(tài)下,系統(tǒng)啟動(dòng)時(shí)若兩種持久化文件同時(shí)存在,則優(yōu)先加載 AOF持久化文件。
2 RDB(Redis DataBase) 持久化
- RDB是指將內(nèi)存中某一時(shí)刻的數(shù)據(jù)快照全量寫(xiě)入到指定的 rdb 文件的持久化技術(shù)。
- RDB 持久化默認(rèn)是開(kāi)啟的,當(dāng) Redis 啟動(dòng)時(shí)會(huì)自動(dòng)讀取 RDB 快照文件,將數(shù)據(jù)從硬盤載入到內(nèi)存,以恢復(fù) Redis 關(guān)機(jī)前的數(shù)據(jù)庫(kù)狀態(tài)
2.1 持久化的執(zhí)行
- RDB 持久化的執(zhí)行有三種方式:手動(dòng) save 命令、手動(dòng) bgsave 命令,與自動(dòng)條件觸發(fā)
2.2 手動(dòng) save 命令
- 通過(guò)在 redis-cli 客戶端中執(zhí)行 save 命令可立即進(jìn)行一次持久化保存。
- **save 命令在執(zhí)行期間會(huì)阻塞 redis-server 進(jìn)程,直至持久化過(guò)程完畢。**而在 redis-server 進(jìn)程阻塞期間,Redis不能處理任何讀寫(xiě)請(qǐng)求,無(wú)法對(duì)外提供服務(wù)。
2.3 手動(dòng) bgsave 命令
- background save,后臺(tái)運(yùn)行 save。
- bgsave 命令會(huì)使服務(wù)器進(jìn)程 redis-server 生成一個(gè)子進(jìn)程,由該子進(jìn)程負(fù)責(zé)完成保存過(guò)程。在子進(jìn)程進(jìn)行保存過(guò)程中,不會(huì)阻塞 redis-server 進(jìn)程對(duì)客戶端讀寫(xiě)請(qǐng)求的處理
- 通過(guò)在 redis-cli 客戶端中執(zhí)行 bgsave 命令可立即進(jìn)行一次持久化保存。
2.4 自動(dòng)條件觸發(fā)
- 自動(dòng)條件觸發(fā)的本質(zhì)仍是 bgsave 命令的執(zhí)行。用戶通過(guò)在配置文件中做相應(yīng)的設(shè)置后,Redis 會(huì)根據(jù)設(shè)置信息自動(dòng)調(diào)用 bgsave 命令執(zhí)行。
2.5 查看持久化時(shí)間
- 通過(guò) lastsave 命令可以查看最近一次執(zhí)行持久化的時(shí)間,其返回的是一個(gè) Unix 時(shí)間戳
3 RDB 優(yōu)化配置
- RDB 相關(guān)的配置在
redis.conf
文件的SNAPSHOTTING
部分
3.1 save
# Save the DB to disk.
#保存DB到磁盤
# save <seconds> <changes> [<seconds> <changes> ...]
#
# Redis will save the DB if the given number of seconds elapsed and it
# surpassed the given number of write operations against the DB.
#如果給定的秒數(shù)過(guò)去了超過(guò)了給定的對(duì)DB的寫(xiě)操作數(shù),Redis將保存數(shù)據(jù)庫(kù)
#
# Snapshotting can be completely disabled with a single empty string argument
#snapshot可以用一個(gè)空字符串參數(shù)完全禁用
# as in following example:
# save ""
#
# Unless specified otherwise, by default Redis will save the DB:
# * After 3600 seconds (an hour) if at least 1 change was performed
# * After 300 seconds (5 minutes) if at least 100 changes were performed
# * After 60 seconds if at least 10000 changes were performed
#
# You can set these explicitly by uncommenting the following line.
#
# save 3600 1 300 100 60 100
#除非另有說(shuō)明,默認(rèn)情況下Redis會(huì)保存DB:
# * 3600秒后(一個(gè)小時(shí)),如果至少執(zhí)行了一次更改
# * 在300秒(5分鐘)后,如果執(zhí)行了至少100次更改
# * 如果執(zhí)行了至少10000次更改,則在60秒后
#你可以通過(guò)取消注釋下面的行顯式設(shè)置。
# save 3600 1 300 100 60 100
- 該配置用于設(shè)置快照的自動(dòng)保存觸發(fā)條件(save point)。該觸發(fā)條件是在指定時(shí)間段內(nèi)發(fā)生了指定次數(shù)的寫(xiě)操作。除非另有規(guī)定,默認(rèn)情況下持久化條件為
save 3600 1 300 100 60 10000
# save 3600 1 300 100 60 10000 save 3600 1 # 在 3600 秒(1 小時(shí))內(nèi)發(fā)生 1 次寫(xiě)操作 save 300 100 # 在 300 秒(5 分鐘)內(nèi)發(fā)生 100 次寫(xiě)操作 save 60 10000 # 在 60 秒(1 分鐘)內(nèi)發(fā)生 1 萬(wàn)次寫(xiě)操作
- 如果不啟用 RDB 持久化,只需設(shè)置 save 的參數(shù)為空串即可:
save " "
3.2 stop-write-on-bgsave-error
# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#默認(rèn)情況下,如果啟用RDB快照,Redis將停止接受寫(xiě)操作(至少一個(gè)保存點(diǎn))和最新的后臺(tái)保存失敗。
#這將使用戶意識(shí)到(以一種艱難的方式)數(shù)據(jù)沒(méi)有持久化在磁盤上,否則很可能沒(méi)有人會(huì)注意到災(zāi)難將會(huì)發(fā)生。
#
# If the background saving process will start working again Redis will
# automatically allow writes again.
#如果后臺(tái)保存進(jìn)程將重新開(kāi)始工作,Redis將自動(dòng)允許再次寫(xiě)入。
#
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth.
#但是,如果您已經(jīng)設(shè)置了適當(dāng)?shù)腞edis服務(wù)器監(jiān)控和持久性,你可能想要禁用這個(gè)功能,以便Redis將繼續(xù)正常工作,即使磁盤有問(wèn)題,permissions,等。
- 默認(rèn)情況下,如果 RDB 快照已啟用(至少一個(gè)保存點(diǎn)),且最近的 bgsave 命令失敗,Redis將停止接受寫(xiě)入。這樣設(shè)置是為了讓用戶意識(shí)到數(shù)據(jù)沒(méi)有正確地保存到磁盤上,否則很可能沒(méi)有人會(huì)注意到,并會(huì)發(fā)生一些災(zāi)難。當(dāng)然,如果 bgsave 命令后來(lái)可以正常工作了,Redis將自動(dòng)允許再次寫(xiě)入
3.3 rdbcompression
- 當(dāng)進(jìn)行持久化時(shí)啟用 LZF 壓縮字符串對(duì)象。雖然壓縮 RDB 文件會(huì)消耗系統(tǒng)資源,降低性能,但可大幅降低文件的大小,方便保存到磁盤,加速主從集群中從節(jié)點(diǎn)的數(shù)據(jù)同步。
3.4 rdbchecksum
- 從 RDB5 開(kāi)始,RDB 文件的 CRC64 校驗(yàn)和就被放置在了文件末尾。這使格式更能抵抗 RDB文件的損壞,但在保存和加載 RDB 文件時(shí),性能會(huì)受到影響(約 10%),因此可以設(shè)置為 no禁用校驗(yàn)和以獲得最大性能。
- 在禁用校驗(yàn)和的情況下創(chuàng)建的 RDB 文件的校驗(yàn)和為零,這將告訴加載代碼跳過(guò)校驗(yàn)檢查。默認(rèn)為 yes,開(kāi)啟了校驗(yàn)功能。
3.5 sanitize-dump-payload
- 該配置用于設(shè)置在加載 RDB 文件或進(jìn)行持久化時(shí)是否開(kāi)啟對(duì) zipList、listPack 等數(shù)據(jù)的全面安全檢測(cè)。該檢測(cè)可以降低命令處理時(shí)發(fā)生系統(tǒng)崩潰的可能。其可設(shè)置的值有三種選擇:
- no:不檢測(cè)
- yes:總是檢測(cè)
- clients:只有當(dāng)客戶端連接時(shí)檢測(cè)。排除了加載 RDB 文件與進(jìn)行持久化時(shí)的檢測(cè)。
- 默認(rèn)值本應(yīng)該是 clients,但其會(huì)影響 Redis 集群的工作,所以默認(rèn)值為 no,不檢測(cè)
3.6 dbfilename
- 指定
RDB
文件的默認(rèn)名稱,默認(rèn)為dump.rdb
3.7 rdb-del-sync-files
- 主從復(fù)制時(shí),是否刪除用于同步的從機(jī)上的 RDB 文件。默認(rèn)是 no,不刪除。
- 注意:只有當(dāng)從機(jī)的 RDB 和 AOF 持久化功能都未開(kāi)啟時(shí)才生效。
3.8 dir
- 指定 RDB 與 AOF 文件的生成目錄。默認(rèn)為 Redis 安裝根目錄
4 RDB 文件結(jié)構(gòu)
- RDB 持久化文件 dump.rdb 整體上有五部分構(gòu)成
-
SOF:常量,一個(gè)字符串 REDIS,僅包含這五個(gè)字符,其長(zhǎng)度為 5。用于標(biāo)識(shí) RDB文件的開(kāi)始,以便在加載 RDB 文件時(shí)可以迅速判斷出文件是否是 RDB 文件。
-
rdb_version:整數(shù),長(zhǎng)度為 4 字節(jié),表示 RDB 文件的版本號(hào)。
-
EOF:常量,占 1 個(gè)字節(jié),用于標(biāo)識(shí) RDB 數(shù)據(jù)的結(jié)束,校驗(yàn)和的開(kāi)始。
-
check_sum:校驗(yàn)和 check_sum 用于判斷 RDB 文件中的內(nèi)容是否出現(xiàn)數(shù)據(jù)異常。其采用的是 CRC 校驗(yàn)算法。
- CRC 校驗(yàn)算法:
- 在持久化時(shí),先將 SOF、rdb_version 及內(nèi)存數(shù)據(jù)庫(kù)中的數(shù)據(jù)快照這三者的二進(jìn)制數(shù)據(jù)拼接起來(lái),形成一個(gè)二進(jìn)制數(shù)(假設(shè)稱為數(shù) a),然后再使用這個(gè) a 除以校驗(yàn)和 check_sum,此時(shí)可獲取到一個(gè)余數(shù) b,然后再將這個(gè) b 拼接到 a 的后面,形成 databases。
- 在加載時(shí),需要先使用 check_sum 對(duì) RDB 文件進(jìn)行數(shù)據(jù)損壞驗(yàn)證。驗(yàn)證過(guò)程:只需將RDB 文件中除 EOF 與 check_sum 外的數(shù)據(jù)除以 check_sum。只要除得的余數(shù)不是 0,就說(shuō)明文件發(fā)生損壞。當(dāng)然,如果余數(shù)是 0,也不能肯定文件沒(méi)有損壞。
- 這種驗(yàn)證算法,是數(shù)據(jù)損壞校驗(yàn),而不是數(shù)據(jù)沒(méi)有損壞的校驗(yàn)。
- CRC 校驗(yàn)算法:
-
databases:可以包含任意多個(gè)非空數(shù)據(jù)庫(kù)。而每個(gè) database 又是由三部分構(gòu)成:
-
SODB:是一個(gè)常量,占 1 個(gè)字節(jié),用于標(biāo)識(shí)一個(gè)數(shù)據(jù)庫(kù)的開(kāi)始。
-
db_number:數(shù)據(jù)庫(kù)編號(hào)。
-
key_value_pairs:當(dāng)前數(shù)據(jù)庫(kù)中的鍵值對(duì)數(shù)據(jù)。
-
每個(gè) key_value_pairs 又由很多個(gè)用于描述鍵值對(duì)的數(shù)據(jù)構(gòu)成。
- VALUE_TYPE:是一個(gè)常量,占 1 個(gè)字節(jié),用于標(biāo)識(shí)該鍵值對(duì)中 value 的類型。
- EXPIRETIME_UNIT:是一個(gè)常量,占 1 個(gè)字節(jié),用于標(biāo)識(shí)過(guò)期時(shí)間的單位是秒還是毫秒。
- time:當(dāng)前 key-value 的過(guò)期時(shí)間。
-
5 RDB 持久化過(guò)程
- 對(duì)于 Redis 默認(rèn)的 RDB 持久化,在進(jìn)行 bgsave 持久化時(shí),redis-server 進(jìn)程會(huì) fork 出一個(gè) bgsave 子進(jìn)程,由該子進(jìn)程以異步方式負(fù)責(zé)完成持久化。而在持久化過(guò)程中,redis-server進(jìn)程不會(huì)阻塞,其會(huì)繼續(xù)接收并處理用戶的讀寫(xiě)請(qǐng)求。
-
bgsave 子進(jìn)程的詳細(xì)工作原理如下:
- 由于子進(jìn)程可以繼承父進(jìn)程的所有資源,且父進(jìn)程不能拒絕子進(jìn)程的繼承權(quán)。所以,bgsave 子進(jìn)程有權(quán)讀取到 redis-server 進(jìn)程寫(xiě)入到內(nèi)存中的用戶數(shù)據(jù),使得將內(nèi)存數(shù)據(jù)持久化到 dump.rdb 成為可能。
- bgsave 子進(jìn)程在持久化時(shí)首先會(huì)將內(nèi)存中的全量數(shù)據(jù) copy 到磁盤中的一個(gè) RDB 臨時(shí)文件,copy 結(jié)束后,再將該文件 rename 為 dump.rdb,替換掉原來(lái)的同名文件。
- 在進(jìn)行持久化過(guò)程中,如果 redis-server 進(jìn)程接收到了用戶寫(xiě)請(qǐng)求,則系統(tǒng)會(huì)將內(nèi)存中發(fā)生數(shù)據(jù)修改的物理塊 copy 出一個(gè)副本。等內(nèi)存中的全量數(shù)據(jù) copy 結(jié)束后,會(huì)再將副本中的數(shù)據(jù) copy 到 RDB 臨時(shí)文件。這個(gè)副本的生成是由于 Linux 系統(tǒng)的**寫(xiě)時(shí)復(fù)制技術(shù)(Copy-On-Write)**實(shí)現(xiàn)的。
6 補(bǔ)充寫(xiě)實(shí)復(fù)制技術(shù)
- 寫(xiě)時(shí)復(fù)制技術(shù)是 Linux 系統(tǒng)的一種進(jìn)程管理技術(shù)。
- 原本在 Unix 系統(tǒng)中,當(dāng)一個(gè)主進(jìn)程通過(guò) fork()系統(tǒng)調(diào)用創(chuàng)建子進(jìn)程后,內(nèi)核進(jìn)程會(huì)復(fù)制主進(jìn)程的整個(gè)內(nèi)存空間中的數(shù)據(jù),然后分配給子進(jìn)程。這種方式存在以下問(wèn)題:
- 這個(gè)過(guò)程非常耗時(shí)
- 這個(gè)過(guò)程降低了系統(tǒng)性能
- 如果主進(jìn)程修改了其內(nèi)存數(shù)據(jù),子進(jìn)程副本中的數(shù)據(jù)是沒(méi)有修改的。即出現(xiàn)了數(shù)據(jù)冗余,而冗余數(shù)據(jù)最大的問(wèn)題是數(shù)據(jù)一致性無(wú)法保證。
- 現(xiàn)代的 Linux 則采用了更為有效的方式:寫(xiě)時(shí)復(fù)制。子進(jìn)程會(huì)繼承父進(jìn)程的所有資源,其中就包括主進(jìn)程的內(nèi)存空間。即子進(jìn)程與父進(jìn)程共享內(nèi)存。只要內(nèi)存被共享,那么該內(nèi)存就是只讀的(寫(xiě)保護(hù)的)。而寫(xiě)時(shí)復(fù)制則是在任何一方需要寫(xiě)入數(shù)據(jù)到共享內(nèi)存時(shí)都會(huì)出現(xiàn)異常,此時(shí)內(nèi)核進(jìn)程就會(huì)將需要寫(xiě)入的數(shù)據(jù) copy 出一個(gè)副本寫(xiě)入到另外一塊非共享內(nèi)存區(qū)域。