淺談:Redis持久化機制(一)RDB篇

帝莘發表於2021-06-04

淺談:Redis持久化機制(一)RDB篇

​ 眾所周知,redis是一款效能極高,基於記憶體的鍵值對NoSql資料庫,官方顯示,它的讀效率可達到11萬次每秒,寫效率能達到8萬次每秒,因為它基於記憶體以及存讀效率高的特性,在市場上的應用中一般都把它作為快取來使用,同時這也意味著它不能大量的無限制的填充資料,否則容易記憶體填滿,導致redis會向硬碟申請虛擬記憶體,造成記憶體和外存的不斷I/O,致使效率低下,甚至引起當機,那麼問題來了,既然只是當做快取而不是為了永久儲存資料,redis為什麼要做持久化呢?這樣做有什麼意義呢?

1.為什麼要做持久化

  • 第一點要明確,redis作為記憶體資料庫,當機後就會發生資料消失,之所以要去做持久化只是為了能在重啟之後快速的恢復資料,而不是儲存資料;redis的持久化並不能夠保證資料的完整性.
  • 當然,如果要把redis當做DB用,DB資料要完整,所以需要一個完整的資料來源(比如mysql),當啟動時將資料來源的資料全部載入到redis裡面,這只適用於資料量小的不易改變的,比如:字典庫。像mysql那樣大量的儲存資料是行不通的。

2.RDB(redis database)

​ 說完redis持久化的原因,我們再詳聊一下redis做持久化的第一種方式RDB,這種方式也是redis預設的一種持久化方式,預設是開啟的。

​ 從字面上來看,RDB也就是redis database,翻譯成中文就是redis 資料庫,也就是說這種持久化方式就是像資料庫一樣儲存了資料,當然事實上也是這樣的,RDB方式是通過儲存快照資料來完成的,既然是快照資料,那就是說明這種方式只關注了某一刻快取的資料狀態,關注的是那一刻資料是什麼,它並沒有去記錄這個資料變更的一系列過程。也就是說,RDB持久化方式關注的是資料儲存的結果,而非是資料儲存的過程。

​ 另外,既然是快照資料,redis又要保證效能,因此要明白RDB持久化時肯定不會是實時的,肯定是隔一段時間觸發一次,否則的話redis作為一個單執行緒處理的服務,光顧著去持久化資料了,怎麼還有時間處理來自客戶端的請求訪問,這也就說明了由於有時間間隔,redis的RDB方式的持久化會丟失最後一次持久化後的資料,這也就表明了redis的持久化沒有辦法保證資料的完整性。

2.1 觸發快照的方式

  • 配置引數定期執行(在redis.conf中配置:save 多少秒內 資料變了多少)
save ""  # 不使用RDB儲存  不能主從
save 900 1  # 表示15分鐘(900秒鐘)內至少1個鍵被更改則進行快照。
save 300 10 # 表示5分鐘(300秒)內至少10個鍵被更改則進行快照。
save 60 10000 # 表示1分鐘內至少10000個鍵被更改則進行快照。
  • 命令顯式觸發(save或者bgsave命令)

    127.0.0.1:6379> bgsave
    Background saving started
    

2.2 RDB執行流程

1.redis父程式首先判斷,當前是否正在執行save,如果正在執行,則先返回。

2.父程式fork()複製出子程式,在這個過程中父程式是阻塞的,不再處理redis接收到的其他命令。當父程式fork結束,又可以重新處理工作。

3.子程式建立RDB檔案,根據父程式的記憶體快照生成臨時快照檔案,完成後對原有的檔案進行替換。始終保持RDB檔案的完整性。

4.子程式生成RDB檔案完成後,就響應資訊給父程式,父程式更新統計資訊。

2.3 RDB檔案結構

1、頭部5位元組固定為“REDIS”字串
2、4位元組“RDB”版本號(不是Redis版本號),當前為9,填充後為0009
3、輔助欄位,以key-value的形式

欄位名 欄位值 欄位名 欄位值
redis-ver 5.0.5 aof-preamble 是否開啟aof
redis-bits 64/32 repl-stream-db 主從複製
ctime 當前時間戳 repl-id 主從複製
used-mem 使用記憶體 repl-offset 主從複製

4、儲存資料庫號碼
5、字典大小6、過期key
7、主要資料,以key-value的形式儲存
8、結束標誌
9、校驗和,就是看檔案是否損壞,或者是否被修改。

2.4 RDB的優缺點

優點:

  • RDB是二進位制壓縮檔案,佔用空間小,便於傳輸。(做主從複製時傳遞給slaver效率也很高)
  • 通過主程式fork複製子程式,由子程式完成持久化的方式,這樣可以最大化的保證redis的效能。但是前提條件是redis的資料量不能太大,否則fork的過程太長,容易造成阻塞。

缺點:

  • 不能保證資料的完整性,會丟失最後一次fork之後的資料。例如,redis進行持久化的操作是1分鐘一次,當上次持久化完成後的30秒內,新新增了5000個資料,那麼redis發生當機然後重新恢復時,那30秒的資料會丟失。

相關文章