京東網(wǎng)站建設步驟關鍵詞排名關鍵詞快速排名
文章目錄
- Redis 持久化
- 1 持久化基本原理
- 2 RDB(Redis DataBase) 持久化
- 2.1 持久化的執(zhí)行
- 2.2 手動 save 命令
- 2.3 手動 bgsave 命令
- 2.4 自動條件觸發(fā)
- 2.5 查看持久化時間
- 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 文件結構
- 5 RDB 持久化過程
- 6 補充寫實復制技術
Redis 持久化
- Redis 是一個內存數(shù)據(jù)庫,所以其運行效率非常高。但是存在一個問題:內存中的數(shù)據(jù)是不持久的,若主機宕機或 Redis 關機重啟,則內存中的數(shù)據(jù)全部丟失。Redis 具有持久化功能,其會按照設置以快照或操作日志的形式將數(shù)據(jù)持久化到磁盤。
- 根據(jù)持久化使用技術的不同,Redis 的持久化分為兩種:RDB 與 AOF
1 持久化基本原理

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