天天看點

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

2 RDB(Redis database)- 全量寫入

Redis Server在有多db 中存儲的K.V可了解為Redis的一個狀态。當發生寫操作時,Redis就會從一個狀态切換到另外一個狀态。

基于全量的持久化就是在某個時刻,将Redis的所有資料持久化到硬碟中,形成一個快照。快照,顧名思義可以了解為拍照一樣,把整個記憶體資料映射到硬碟中,儲存一份到硬碟,是以恢複資料起來比較快,把資料映射回去即可,不像 AOF,一條條的執行操作指令。

當Redis 重新開機時,通過加載最近一個快照資料,可以将 Redis 恢複至最近一次持久化狀态上。

快照是預設的持久化方式。這種方式是就是将記憶體中資料以快照的方式寫入到二進制檔案中,預設的檔案名為 dump.rdb。

2.1 觸發方式

save

  • 用戶端顯示觸發
  • 或用戶端發送 shutdown 指令,系統會先執行 save 指令阻塞用戶端,然後關閉伺服器

save本身是

單線程串行

方式執行,是以當資料量大時,可能會發生Redis Server的長時間卡頓。

其備份期間其他指令全部阻塞,無法執行,是以備份時期

資料的狀态始終一緻

若存在老的RDB檔案,則新的會替換老的,時間複雜度O(N)。

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

設定 redis.conf

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

再使用腳本初始化 500w 資料,等待後發現已經落盤:

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

bgsave

bgsave 可由

  • 用戶端顯式觸發
  • 配置定時任務觸發
  • 當有主從架構時,從伺服器向主伺服器發送 sync 指令來執行複制操作時,主伺服器會執行 bgsave

bgsave指令在執行時,會fork一個子程序。子程序送出完成後,會立即給用戶端傳回響應,備份操作在背景異步執行,期間不會影響Redis的正常響應。

對于bgsave來說,當父程序Fork完子程序之後,異步任務會将目前的記憶體狀态作為一個版本進行複制。在複制過程中産生的變更,不會反映在這次備份當中。

不用指令,而使用配置

在Redis的預設配置中,當滿足下面任一條件,會自動觸發 bgsave 的執行:

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

bgsave相對于save的優勢是

異步執行

,不影響後續指令執行。但Fork子程序,涉及父程序的記憶體複制,會增加伺服器記憶體開銷。

當記憶體開銷高到使用虛拟記憶體時,bgsave的Fork子程序會阻塞運作

,可能會造成秒級不可用。是以使用bgsave需要保證伺服器空閑記憶體足夠。

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐
Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

2.2 RDB執行流程

rdb.c檔案執行流程:

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

2.3 RDB 最佳配置

關閉自動RDB:

dbfilename dump-${port}.rdb
dir /redisDataPath
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes      

需要注意的觸發時機

  • 主從複制時機的全量複制,master節點會執行bgsave
  • debug reload
  • shutdown
  • flushDB 、 flushAll

2.4 RDB性質

  1. RDB是Redis記憶體到硬碟的快照,用于持久化
  2. save通常會阻塞Redis
  3. bgsave不會阻塞Redis,但會fork新程序
  4. save自動配置滿足任一就會被執行

2.5 RDB 優點

  • 緊湊壓縮的二進制檔案

    RDB會生成多個資料檔案,每個檔案都代表了某時刻Redis中的所有資料,這種方式非常适合做冷備。可将這種完整資料檔案發送到雲伺服器存儲,比如ODPS分布式存儲,以預定好的備份政策來定期備份Redis中的資料

  • fork子程序性能最大化

    RDB對Redis對外提供的讀寫服務,影響非常小,可讓Redis保持高性能,因為Redis主程序隻要fork一個子程序,讓子程序執行RDB

  • 啟動效率高

    相對于AOF,直接基于RDB檔案重新開機和恢複Redis程序,更加快速

2.6 RDB缺點

耗時

O(n)

寫時複制(copy-on-write)

耗記憶體,copy-on-write政策。RDB每次在fork子程序來執行RDB快照資料檔案生成的時候,如果資料檔案特别大,可能會導緻對用戶端提供的服務暫停數毫秒,或者甚至數秒。

執行 fork 時,os會使用寫時複制,即 fork 函數發生的一刻父子程序共享同一記憶體資料。當父程序要更改其中某片資料時(如執行一個寫指令),os會将該片資料複制一份以保證子程序資料不受影響,是以新的 RDB 檔案存儲的是執行 fork 一刻的記憶體資料。

不可控

容易丢失資料。一般RDB每隔5分鐘,或者更長時間生成一次,若過程中Redis當機,就會丢失最近未持久化的資料

2.7 恢複流程

當Redis重新啟動時,會從本地磁盤加載之前持久化的檔案。當恢複完成之後,再受理後續的請求操作。

4 選型及最佳實踐

Redis的持久化機制(下)2 RDB(Redis database)- 全量寫入4 選型及最佳實踐

混合持久化

Redis 4.0 開始支援 RDB 和 AOF 的混合持久化(預設關閉,通過配置項

aof-use-rdb-preamble

開啟)。

如果把混合持久化打開,AOF 重寫時就直接把 RDB 内容寫到 AOF 檔案開頭:

  • 好在可以結合 RDB 和 AOF 的優點, 快速加載同時避免丢失過多資料
  • 但是,AOF 裡的 RDB 部分就是壓縮格式不再是 AOF 格式,可讀性較差

RDB最佳政策

  • 關閉
  • 集中手動管理RDB操作
  • 在從節點打開自動執行配置,但是不宜頻繁執行RDB

AOF最佳政策

  • 建議打開,但是如果隻是純作為緩存使用可不開
  • AOF重寫集中管理
  • everysec

抉擇RDB & AOF

不要僅使用RDB,因為那樣會導緻丢失很多資料

也不要僅使用AOF,因為那樣有兩個問題

你通過AOF做冷備,沒有RDB做冷備,來的恢複速度更快

RDB每次簡單粗暴生成資料快照,更加健壯,可以避免AOF這種複雜的備份和恢複機制的bug

綜合使用AOF和RDB

用AOF保證資料不丢失,作為資料恢複的第一選擇

用RDB做不同程度的冷備,在AOF檔案都丢失或損壞不可用時,還可使用RDB快速實作資料恢複

一些最佳實踐

  • 小分片

    例如設定maxmemory參數設定每個redis隻存儲4個G的空間,這樣各種操作都不會太慢

  • 監控(硬碟、記憶體、負載、網絡)
  • 足夠的記憶體

參考

繼續閱讀