Redis原理筆記

......

 

 持久化存儲

 What is persistence

將RAM(內存)中的的數據存儲到能永久保存的ROM(如disk)中。

How to persist

  1. 快照(snapshot),指在某個時刻對數據進行備份持久化,如Mysql的Dump方式、Redis的RDB方式。
  2. 寫日誌,將用戶所有的寫指令(增刪改)保存到日誌文件中,當需恢復數據時重新執行一遍這些指令,如Mysql的Binlog、Redis的AOF、Hbase的HLog。

                              

1 持久化存儲方式

2 持久化存儲原理

2.1 RDB

2.1.1 原理結構

                                             RDB持久化            

  1. RDB是Redis默認的持久化方案,默認開啓
  2. 可以在指定的時間間隔內,執行指定次數的寫操作,將內存中的數據寫入到磁盤中
  3. 可以在指定目錄下自動生成dump.rdb文件,當Redis重啓時會加載該文件以恢復數據
  4. 自動備份和手動備份

2.1.2 工作執行流程——三種主要觸發機制

2.1.2.1 手動觸發之save命令

原理圖

                                save命令

          save命令阻塞所有客戶端的請求

指令

127.0.0.1:6379> save
OK

說明

  1. save命令執行的是同步操作,以RDB文件的方式保存所有數據的快照
  2. 佔用主進程,執行速度非常慢,會阻塞所有的client請求,故很少在生產環境中使用save指令

2.1.2.2 手動觸發之bgsave命令

原理圖1

                          

 

指令

127.0.0.1:6379> bgsave
Background saving started

簡要說明

  1. bgsave命令執行的是異步操作,以RDB文件的方式保存所有數據的快照
  2. Redis調用Linux系統中fork()創建一個子進程將數據保存到磁盤中,主進程繼續服務客戶端的調用
  3. 若操作成功,可以通過客戶端命令LASTSAVE來檢查操作結果;若子進程發生錯誤,用 SAVE命令保存最新的數據

原理圖2

說明

  1. 執行bgsave命令,Redis父進程判斷當前是否存在正在執行的子進程,如果存在則直接返回
  2. 父進程fork一個子進程(fork的過程中會造成阻塞的情況),這個過程可以使用info stats命令查看latest_fork_usec選項,查看最近一次fork操作小號的時間,單位是微秒μs
  3. 父進程fork完之後,則會返回Background saving started信息提示,此時fork阻塞解除
  4. fork出的子進程開始根據父進程內存數據生成臨時的快照文件,然後替換原文件.使用lastsave命令可以查看最後一次生成rdb的時間,對應info的rdb_last_savetime選項
  5. 當備份完畢之後向父進程發送完成信息,具體可以見info Persistence下的rbd*選項

save 與 bgsave 對比

命令 save bgsave
IO類型 同步 異步
阻塞 是(阻塞發生在fock(),通常非常快)
複雜度 O(n) O(n)
優點 不會消耗額外的內存 不阻塞客戶端請求命令
缺點 阻塞客戶端請求命令 需要fock子進程,消耗內存

2.1.2.3 自動觸發

描述:通過redis.conf配置文件對 Redis 進行設置, 讓它在“ N 秒內數據集至少有 M 個改動”這一條件被滿足時, 自動進行數據集保存操作。

自動觸發過程:

  1. 修改配置項 save m n即表示在 m 秒內執行了 n 次命令則進行備份
  2. 當Redis 從服務器項主服務器發送複製請求時,主服務器則會使用 bgsave命令生成 rbd 文件,然後傳輸給從服務器
  3. 當執行 debug reload 命令時也會使用 save 命令生成rdb文件
  4. 當使用 shutdown 命令關掉服務時,如果沒有啓用 aof方式實現持久化則會採用bgsave的方式做持久化。同時shutdown後面可以加備份參數[nosave|save]。

指令:

save  <指定時間間隔>  <執行指定次數更新操作>

舉例:

  1. 以下設置會讓 Redis 在滿足“ 60 秒內有至少有 1000 個鍵被改動”這一條件時, 自動生成rdb文進行數據集保存
save 60 1000

                              自動生成RDB

2.1.2.4 自動觸發的相關配置

1. redis.cnf配置文件(部分)

# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving at all commenting all the "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

說明:

  1. save <指定時間間隔> <執行指定次數更新操作>,滿足條件就將內存中的數據同步到硬盤中
  2. 官方出廠配置默認是 900秒內有1個更改,300秒內有10個更改以及60秒內有10000個更改,則將內存中的數據快照寫入磁盤
  3. 若不想用RDB方案,可以把 save "" 的註釋打開,下面三個註釋

2. vim redis.cfg

# RDB自動持久化規則
# 當 900 秒內有至少有 1 個鍵被改動時,自動進行數據集保存操作
save 900 1
# 當 300 秒內有至少有 10 個鍵被改動時,自動進行數據集保存操作
save 300 10
# 當 60 秒內有至少有 10000 個鍵被改動時,自動進行數據集保存操作
save 60 10000

# RDB持久化文件名
dbfilename dump-<port>.rdb

# 數據持久化文件存儲目錄
dir /var/lib/redis

# bgsave發生錯誤時是否停止寫入,通常爲yes
stop-writes-on-bgsave-error yes

# rdb文件是否使用壓縮格式
rdbcompression yes

# 是否對rdb文件進行校驗和檢驗,通常爲yes
rdbchecksum yes


另:

# 1. 將自動生成rdb文件註釋掉
# save 900 1
# save 300 10
# save 60 10000

# The filename where to dump the DB
# 2. rdb的文件名,改爲dump+ 端口.rbd
dbfilename dump-${port}.rdb


# Note that you must specify a directory here, not a file name.
# 3. 文件持久化目錄,日誌目錄,改到分佈式存儲中或者放到較大的硬盤目錄中。
dir /yourbigdata/

# 4. 在bgsave發生錯誤時停止寫入
stop-writes-on-bgsave-error yes

# 5.採用壓縮方式,不然生成的rdb文件可能巨大無比。壓縮後主從複製拷貝文件小,速度也快。
rdbcompression yes

# 6.採用校驗和
rdbchecksum yes

RDB優缺點

優點

  1. 非常適用數據集備份、rdb文件拷貝進行文件傳輸
  2. 如果業務對數據完整性和一致性要求不高,RDB是很好的選擇
  3. RDB文件採用壓縮的二進制文件,當重啓服務時加載數據文件,比aof方式更快

缺點

  • 不可控,容易丟失數據,導致數據的完整性和一致性不高,因爲RDB可能在最後一次備份時宕機了

如果你希望在redis意外停止工作(例如電源中斷)的情況下丟失的數據最少的話,那麼RDB不適合你。雖然你可以配置不同的save時間點(例如每隔5分鐘並且對數據集有100個寫的操作),是Redis要完整的保存整個數據集是一個比較繁重的工作,你通常會每隔5分鐘或者更久做一次完整的保存,萬一在Redis意外宕機,你可能會丟失幾分鐘的數據(轉:https://segmentfault.com/a/1190000016021217

  • 耗時、耗性能:備份時佔用內存,因爲Redis 在備份時會獨立創建一個子進程,將數據寫入到一個臨時文件(此時內存中的數據是原來的兩倍),最後再將臨時文件替換之前的備份文件。Redis 的持久化和數據的恢復要選擇在夜深人靜的時候執行。

RDB 需要經常fork子進程來保存數據集到硬盤上,當數據集比較大的時候,fork的過程是非常耗時的,可能會導致Redis在一些毫秒級內不能響應客戶端的請求。如果數據集巨大並且CPU性能不是很好的情況下,這種情況會持續1秒,AOF也需要fork,但是你可以調節重寫日誌文件的頻率來提高數據集的耐久度。(轉:https://segmentfault.com/a/1190000016021217

  • rbd採用加密的二進制格式存儲文件,由於Redis各個版本之間的兼容性問題也導致rdb由版本兼容問題導致無法再其他的Redis版本中使用。

2.1.2.5  RDB文件常見的處理方式

  • 當遇到磁盤寫滿情況,可以使用如下命令來切換存儲磁盤
# dirName則是新的存儲目錄名(該方式同樣適用於aof格式)
config set dir dirName
  • 文件壓縮處理,雖然對CPU具有消耗,但是減少體積的暫用,同時做文件傳輸(主從複製)也減少消耗
# 修改壓縮開啓或關閉
config set rdbcompression yes|no
  • rbd備份文件損壞檢測.可以使用redis-check-rdb工具檢測rdb文件,該工具默認在/usr/local/bin/目錄下面
[root@root redis-data]# /usr/local/bin/redis-check-rdb ./6379-rdb.rdb 
[offset 0] Checking RDB file ./6379-rdb.rdb
[offset 26] AUX FIELD redis-ver = '5.0.3'
[offset 40] AUX FIELD redis-bits = '64'
[offset 52] AUX FIELD ctime = '1552061947'
[offset 67] AUX FIELD used-mem = '852984'
[offset 83] AUX FIELD aof-preamble = '0'
[offset 85] Selecting DB ID 0
[offset 105] Checksum OK
[offset 105] \o/ RDB looks OK! \o/
[info] 1 keys read
[info] 0 expires
[info] 0 already expired

2.2 AOF

update...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發佈了37 篇原創文章 · 獲贊 24 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章