Redis-RDB-AOF持久化篇

以往的文章:

一、Redis-數據類型與其應用場景

二、Redis-通用指令篇

Redis-RDB-AOF持久化篇

Redis簡介

Redis是C語言開發的一個高性能鍵值對(key -value) 內存數據庫,可以用作數據庫,緩存和消息中間件等。

特點

  1. 作爲內存數據庫,它的性能非常優秀,數據存儲在內存當中,讀寫速度非常快,支持併發10W QPS(每秒查詢次數),單進程單線程,是線程安全的,採用IO多路複用機制。

  2. 豐富的數據類型,支持字符串,散列,列表,集合,有序集合等,支持數據持久化。可以將內存中數據保存在磁盤中,重啓時加載。

  3. 主從複製,哨兵,高可用,可用作分佈式鎖。可以作爲消息中間件使用,支持發佈訂閱。

什麼是持久化?

舉個例子:
有沒有試過在寫文件(如寫論文時用的Word)的時候,突然遇到斷電或者是軟件崩潰之類的情況,但是我們在遇到文件崩潰的時候,軟件往往有一個自動備份的機制,以致於我們在遇到突然斷電或者軟件崩潰,來不及保存的情況下提供的一個恢復的可能。
在這裏插入圖片描述
在這裏插入圖片描述
那麼所謂的自動備份,自動恢復是怎麼回事呢?其實就是將內存中的數據將硬盤中的數據做了一個關聯,在一段時間以後,將內存中的數據保存到了硬盤上,等到萬一數據丟失了,它會把硬盤的數據再讀回到內存中,把數據恢復了,用這種形式來對數據起到一個保護的作用。
Redis作爲一個內存數據庫,數據如果丟失,會很麻煩,顯然也需要這樣一個機制來保存數據,需要經常同步內存中的數據到硬盤保證持久化。

內存
===》所以:
持久化是將程序數據在持久狀態和瞬時狀態間轉換的機制。通俗的講,就是瞬時數據(比如內存中的數據,是不能永久保存的)持久化爲持久數據(比如持久化至數據庫中,能夠長久保存)。
如:

應用層:如果關閉(shutdown)你的應用然後重新啓動則先前的數據依然存在。

系統層:如果關閉(shutdown)你的系統(電腦)然後重新啓動則先前的數據依然存在。

可見:持久化保存的是數據

Redis 的持久化方式 RDB 和 AOF

RDB快照

快照: 指的是在規定的時間間隔內將內存中的數據集寫入到磁盤中,通俗地說就是像照相機一樣,快門一閃,就可以將某一歷史時刻的景象留在了照片上,不同的是拍照的對象是數據,而不是其他畫面。所以我們可以快速地根據快照來查找到某一歷史時刻的數據信息。

利用快照來對當前數據狀態結果進行保存,格式簡單,關注點在數據。但是快照時間點後面的數據都會丟失。

在Redis中我們可以每隔1分鐘保存一次快照,這樣就算遇到斷電或者其他突發情況,我們損失的一小部分數據影響也不大。

RDB提供了兩種指令來生成RDB文件,每執行一遍,就保存一遍快照

save 命令

因爲 Redis 是單線程的,假定有幾個客戶端分別發送幾條指令到服務器,實際上這幾個指令發送過來是會有一定的執行順序的,假如現在有大量執行指令(非save)已經在這個任務序列裏面,等到某客戶端發送了一個 save 指令過來,開始執行RDB,一旦時間過長,就會阻塞 Redis 服務器進程,且 Redis 服務器在阻塞過程中,不能處理任何其他命令,直到RDB文件創建過程完畢爲止,纔可以往下執行。這樣子就影響了Redis的正常使用,所以線上環境不建議使用,有可能造成長時間阻塞,效率降低。

save // 返回 OK

在這裏插入圖片描述
save 執行的日誌信息:

[4928] 09 Jun 18:04:45.165 * DB saved on disk

bgsave 命令

解決前面的單線程執行方式造成阻塞問題,引入了bgsave這個命令,在執行這個命令的時候,服務器首先返回:Background saving started再在空閒時間調用fork函數派生出一個子進程,然後由子進程負責創建 RDB 文件,父進程繼續處理其他命令請求,子進程創建完畢後,會在日誌中返回這樣一個信息Background saving terminated with success

bgsave // 返回 Background saving started

在這裏插入圖片描述


客戶端redis子進程RDB文件發送:bgsave返回:Background saving started調用:fork函數,生成子進程子進程創建 .rdb 文件子進程創建 .rdb 文件客戶端redis子進程RDB文件

bgsave 執行的日誌信息:

[4928] 09 Jun 17:11:42.834 * Background saving started by pid 9480  開始
[4928] 09 Jun 17:11:43.078 # fork operation complete
[4928] 09 Jun 17:11:43.080 * Background saving terminated with success  結束

注意:bgsave命令是針對save阻塞這個問題做的優化,。Redis內部所有涉及到RDB操作都採用bgsave方式進行,基本上可以不用save了在這裏插入圖片描述

執行成功後生成的文件:
在這裏插入圖片描述
打開文件,在RDB中保存的形式爲二進制,大概就是些數據頭+Redis版本號+數據內容
在這裏插入圖片描述
rdb文件數據:
在這裏插入圖片描述

命令執行完成後會在下面redis.windows.conf文件(linux爲redis.conf)配置的目錄下生成,默認文件名dump.rdb,我們可以根據需求來修改配置
在這裏插入圖片描述
配置文件:

# 後臺存儲過程中如果出現錯誤,是否停止報錯操作,默認開啓—— bgsave
stop-writes-on-bgsave-error yes

# 設置是否壓縮數據,默認爲YES,採用 LZF 壓縮
# 不壓縮可以節省時間,但存儲的文件會更大
rdbcompression yes

# 是否進行RDN文件格式校驗,在文件讀寫過程都會進行
# 默認開啓,如果不開啓,可以節約讀寫過程時間,但是有數據損壞風險
rdbchecksum yes

# The filename where to dump the DB
# 設置本地數據庫文件名,默認值爲dump.rdb,通常設置成 dump-端口號.rdb
dbfilename dump.rdb

# The DB will be written inside this directory, with the filename specified
# 設置存儲.rdb文件的路徑,通常設置到存儲空間較大的目錄中
dir ./

RDB啓動方式:

  • 手工(管理員手工執行命令備份)==》save 命令 | bgsave 命令

  • 自動執行(Redis服務器執行命令備份)==》save second changes

在滿足的second時間範圍內key變化達到changes數量,即執行一次持久化,需要至少changes數量足夠才執行,否則重新計時,如設置10秒內至少5個key改變執行,但是10秒過去了只有2個key改變,則重新計時,在conf文件裏進行新增配置規則save second changes可以配置多個規則,只要滿足其中一個規則就執行

注意事項:

通過配置save second changes 執行的在後臺實際是bgsave操作


RDB三種方式對比:

方式 save命令 bgsave命令 save配置==bgsave命令
讀寫 同步(阻塞) 異步(新進程) 異步
阻塞客戶端 是(單進程) 否(新進程)
額外消耗內存 否(沒有新進程) 是(新進程)
啓動新進程

RDB優點,在上面介紹過一遍了,再做一次總結

  • RDB是一個緊湊壓縮的二進制文件,存儲效率較高
  • RBD內部存儲的是Redis在某個時間點的快照,非常適合於數據備份,全量複製
  • RDB數據恢復速度比AOF快
  • 服務器可以每幾小時執行一次bgsave備份,並將RDB文件複製到遠程機器中,做容災。

RDB缺點,在上面介紹過一遍了,再做一次總結

  • RDB快照方式執行無法做到實時持久化,服務器突然掛了的話,具有較大數據丟失的風險,快照時間點後的數據是沒有的
  • bgsave執行每次都會調用fork函數創建新的子進程做操作,會犧牲部分性能
  • RDB文件格式不統一:數據頭+Redis版本號+數據內容,可能會出現不同版本數據格式不兼容的情況
  • 每次讀寫的都是全部數據,當數據量巨大時,IO性能效率較低

AOF(Append Only File) 過程記錄

過程:
與RDB持久化通過保存數據庫中的鍵值對來記錄數據庫狀態不同,AOF持久化是通過保存Redis所執行的寫命令來記錄數據庫狀態的。如:在PS或者其他工具用的比較多的——“撤回” 功能,在PS歷史記錄就有很好的體現,每執行一個操作,都將它的命令給記錄下來,當我們在操作失誤時,可以調出歷史記錄去選擇恢復到某一步操作的位置
在這裏插入圖片描述
在Redis中就是將命令操作步驟記錄下來,當需要恢復數據的時候,將命令重新執行一遍就可以了。這種方案可以解決數據持久化的實時性上面RDB數據快照時間點後的數據可能丟失),在備份的時候可以沒必要每次都進行全部數據備份,只追加記錄部分數據,並將記錄的數據變爲記錄數據命令的過程。


AOF寫過程

當AOF功能打開時,服務器在執行命令完成之後,服務器沒有直接記錄到AOF文件,而是將被執行的命令寫到一個臨時存儲的區域——AOF_BUFF緩衝區末尾,然後再將命令在一定條件下同步到AOF文件中。

寫命令:set keyredisAOF_BUF緩衝區AOF文件發送到Redis執行執行失敗的執行成功,寫到緩衝區準備進行備份同步寫命令:set keyredisAOF_BUF緩衝區AOF文件

AOF同步條件的三種策略(appendfsync):

  • everysec(系統控制)

AOF_FSYNC_NO :系統來控制同步到AOF文件的週期,根據空閒情況觸發同步,整體過程不可控,系統掛了,損失的數據就隨緣了。。

  • everysec(每秒) Redis默認使用

AOF_FSYNC_EVERYSEC :每一秒鐘將緩衝區命令同步保存一次到AOF文件中,數據準確還是比較高的,且性能會較好。系統突然掛掉,同步損失的就只有那一秒的數據,比較推薦用

  • always(每次)

AOF_FSYNC_ALWAYS :每執行一個命令同步一次到AOF文件,0誤差,但是性能差(同時來個十幾萬條數據,IO消耗大量資源,大概率崩潰

文件配置路徑:redis.windows.conf | redis.conf

注意:如果RDB和AOF同時存在,那麼redis會以AOF爲準,因爲在通常情況下AOF文件保存的數據集要比RDB文件完整

# 默認不開啓,AOF和RDB持久化可以同時啓用,實際場景得根據自己需求了
#appendonly yes 的時候優先級比RDB高
appendonly no

# The name of the append only file (default: "appendonly.aof")
# 默認名:appendonly.aof 可加上端口號:appendonly-端口號.aof
appendfilename "appendonly.aof"

# If unsure, use "everysec".
# 默認使用 everysec
# 下面是三種同步策略
# appendfsync always
appendfsync everysec
# appendfsync no

# 文件保存路徑
dir

AOF 重寫

隨着命令不斷寫入AOF,文件會越來越大,有可能會記錄很多無效或重複的數據,或者是後面的把前面覆蓋的數據,可以將數據進行整理合並。爲了解決這個問題,Redis引入了AOF重寫機制壓縮文件體積,AOF文件重寫是將redis進程內的數據轉化爲寫命令同步到新AOF文件的過程,簡單滴就是說對用一個數據的若干條命令執行結果轉化成最終結果對應的指令進行記錄。

總之重寫乾的就是優化AOF文件的活,減小AOF文件的體積

AOF重寫作用

  • 降低磁盤佔用率,提高磁盤利用率
  • 提高持久化效率,降低持久化寫時間,提高IO性能
  • 降低數據恢復用時,提高恢復效率
  • 例:
可以合併的指令:
lpush list a
lpush list b
lpush list c
可以合併成爲 lpush list a b c ,執行1次總比執行3次效率高
--------------------------------------------------------------------------
無效的指令:
del keya
hdel keyb
srem keyc
可以直接利用內存中的數據來直接生成命令,內存中沒有的數據就不需要生成,這就避免了先添加-再刪除兩步
--------------------------------------------------------------------------
後面的指令已經覆蓋前面的:
set key a
set key b
可以直接利用內存中的數據來直接生成一條添加 b 命令,添加內存本來的 b 數據,這就避免了先添加a-再修改爲 b 兩步
--------------------------------------------------------------------------
進程中已經超時的數據:
setex key seconds values
如果數據超時了,即是此數據已被刪除,無需再寫到文件了,參考無效指令
--------------------------------------------------------------------------

在這裏插入圖片描述
爲了避免在執行命令時造成客戶端輸入緩衝區溢出,重寫程序在處理list、 hash、set、sorted set 等類型,會先檢查鍵所包含的元素數 量,如果元素的數量超過了redis.h的REDIS_AOF_REWRITE_ITEMS_PER_CMD = 64常量的值,那麼重寫程序將使用多條命令來記錄鍵的值,而不單單使用一條命令。

AOF 重寫方式

  • 手動重寫-後臺自動重寫
    在這裏插入圖片描述
bgrewriteaof  // 重寫

流程類似 RDB 的: bgsave 命令

客戶端redis子進程AOF文件發送:bgrewriteaof返回:Background append only file rewriting started調用:fork函數,生成子進程返回消息子進程重寫 .aof 文件子進程創建 .aof 文件客戶端redis子進程AOF文件

AOF文件內容:
在這裏插入圖片描述
執行日誌:

[4928] 09 Jun 21:28:26.356 * Background append only file rewriting started by pid 17824
[4928] 09 Jun 21:28:26.533 * AOF rewrite child asks to stop sending diffs.
[4928] 09 Jun 21:28:26.633 # fork operation complete
[4928] 09 Jun 21:28:26.635 * Background AOF rewrite terminated with success
[4928] 09 Jun 21:28:26.637 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
[4928] 09 Jun 21:28:26.637 * Background AOF rewrite finished successfully
  • 配置自動重寫
# 配置文件:redis.conf | redis.windows.conf

# 自動觸發的條件配置
//這兩個配置項的意思是,在aof文件體量超過64mb,且比上次重寫後的體量增加了100%時自動觸發重寫。我們可以修改這些參數達到自己的實際要求
auto-aof-rewrite-percentage 100  // 自動重寫的百分比增長率,百分比達到100%才重寫
auto-aof-rewrite-min-size 64mb  //觸發重寫的最小容量,不同版本默認值不一樣,緩衝區到64M才進行重寫



# 自動觸發對比參數
    # 基礎大小
    aof_base_size

    # 當前緩衝區容量大小
    aof_current_size
    
    
觸發重寫所需條件;
第一種:當前容量超出設置的最小容量
aof_current_size > auto-aof-rewrite-min-size

第二種:基本大小與當前大小進行比較,如果當前大小大於指定的百分比,將觸發重寫
(aof_current_size - aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage

看圖註釋:
在這裏插入圖片描述
AOF 工作流程

aways(每次都寫入)非重寫

指令set
主進程
執行set
調用fork
AOF文件

everysec(每秒夠後才寫入)非重寫

指令set
主進程
執行set
調用fork
AOF緩衝區
滿足條件後
AOF文件

everysec(每秒夠後才寫入)重寫

指令set
主進程
執行set
調用fork
AOF緩衝區
子進程
滿足條件後
AOF文件
AOF重寫緩衝區
提供數據
開始AOF文件重寫
執行重寫操作
完成AOF文件重寫
新AOF文件
發送信號,通知主進程
執行後續命令
新AOF文件合併替換舊AOF文件

在這裏插入圖片描述

RDB 對比 AOF

持久化方式 RDB AOF
佔用存儲空間 小(數據級:可配置壓縮) 大(指令級:可配置重寫)
存儲速度 慢(每次都得全部存一次) 快(可追加)
恢復速度 快(二進制存儲,直接載入內存) 慢(要重新執行命令,文件大)
數據安全性 會丟失數據(丟失快照時間點後的數據) 依據策略決定 (可能丟失一秒的(每秒),也可能未知(系統調度))
資源消耗 高/重量級(save單進程阻塞/bgsave子進程) 低/輕量級 (不阻塞)
啓動優先級 高(同時開啓是AOF高)
備份選擇 全量備份 增量備份

RDB 和 AOF 選擇

每種都有利有弊,看實際需求。。。。。
對數據非常敏感,不能承受數分鐘以內數據丟失——AOF

能承受數分鐘以內數據丟失,追求大數據恢復速度——RDB

雙保險:綜合使用AOF和RDB兩種持久化機制,使用AOF來保證數據不丟失,作爲數據恢復的第一選擇;用RDB做不同程度的冷備,當AOF備份文件丟失或損壞不可用時,可以使用RDB快照文件快速的恢復數據——RDB+AOF

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章