Redis持久化解讀

一、簡介

  • redis是一個內存數據庫,數據保存在內存中,但是我們都知道內存的數據變化是很快的,也容易發生丟失。幸好Redis還爲我們提供了持久化的機制,分別是RDB(Redis DataBase)和AOF(Append Only File)。 -

  • 持久化是將程序數據在持久狀態和瞬時狀態間轉換的機制。對於程序來說,程序運行中數據是在內存的,如果沒有及時同步寫入到磁盤,那麼一旦斷電或者程序突然奔潰,數據就會丟失了,只有把數據及時同步到磁盤,數據才能永久保存,不會因爲宕機影響數據的有效性。而持久化就是將數據從程序同步到磁盤的一個動作過程。

  • 數據存放於:

    • 內存:高效、斷電(關機)內存數據會丟失
    • 硬盤:讀寫速度慢於內存,斷電數據不會丟失

持久化

二、redis中持久化的兩種方式(RDB和AOF)

在我們安裝了redis之後,所有的配置都是在redis.conf文件中,裏面保存了RDB和AOF兩種持久化機制的各種配置。

1.RDB機制

  • RDB是redis的默認持久化機制

  • RDB其實就是把數據以快照的形式保存在磁盤上。什麼是快照呢,你可以理解成把當前時刻的數據拍成一張照片保存下來。 幾KB快照相當於幾十G的數據

  • RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤。也是默認的持久化方式,這種方式是就是將內存中數據以快照的方式寫入到二進制文件中,默認的文件名爲dump.rdb。

  • 既然RDB機制是通過把某個時刻的所有數據生成一個快照來保存,那麼就應該有一種觸發機制,是實現這個過程。對於RDB來說,提供了三種機制:save、bgsave、自動化。我們分別來看一下

1、save觸發方式

  • 該命令會阻塞當前Redis服務器,執行save命令期間,Redis不能處理其他命令,直到RDB過程完成爲止。具體流程如下:

在這裏插入圖片描述

  • 執行完成時候如果存在老的RDB文件,就把新的替代掉舊的。我們的客戶端可能都是幾萬或者是幾十萬,這種方式顯然不可取。

2、bgsave觸發方式

  • 執行該命令時,Redis會在後臺異步進行快照操作,快照同時還可以響應客戶端請求。具體流程如下:

在這裏插入圖片描述

  • 具體操作是Redis進程執行fork操作創建子進程,RDB持久化過程由子進程負責,完成後自動結束。阻塞只發生在fork階段,一般時間很短。基本上 Redis 內部所有的RDB操作都是採用 bgsave 命令。

3、自動觸發

自動觸發是由我們的配置文件來完成的。在redis.conf配置文件中,裏面有如下配置,我們可以去設置:

save:這裏是用來配置觸發 Redis的 RDB 持久化條件,也就是什麼時候將內存中的數據保存到硬盤。比如“save m n”。表示m秒內數據集存在n次修改時,自動觸發bgsave。

默認如下配置:

#表示900 秒內如果至少有 1 個 key 的值變化,則保存save 900 1#表示300 秒內如果至少有 10 個 key 的值變化,則保存save 300 10#表示60 秒內如果至少有 10000 個 key 的值變化,則保存save 60 10000

不需要持久化,那麼你可以註釋掉所有的 save 行來停用保存功能。

stop-writes-on-bgsave-error :默認值爲yes。當啓用了RDB且最後一次後臺保存數據失敗,Redis是否停止接收數據。這會讓用戶意識到數據沒有正確持久化到磁盤上,否則沒有人會注意到災難(disaster)發生了。如果Redis重啓了,那麼又可以重新開始接收數據了

rdbcompression :默認值是yes。對於存儲到磁盤中的快照,可以設置是否進行壓縮存儲。

rdbchecksum :默認值是yes。在存儲快照後,我們還可以讓redis使用CRC64算法來進行數據校驗,但是這樣做會增加大約10%的性能消耗,如果希望獲取到最大的性能提升,可以關閉此功能。

dbfilename :設置快照的文件名,默認是 dump.rdb

dir:設置快照文件的存放路徑,這個配置項一定是個目錄,而不能是文件名。

  • 我們可以修改這些配置來實現我們想要的效果。因爲第三種方式是配置的,所以我們對前兩種進行一個對比:
    在這裏插入圖片描述

4、RDB的優勢與劣勢

  • 優勢:
    • RDB文件緊湊,全量備份,非常適合用於進行備份和災難恢復。
    • 生成RDB文件的時候,redis主進程會fork()一個子進程來處理所有保存工作,主進程不需要進行任何磁盤IO操作。
    • RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。
  • 劣勢:
    • RDB快照是一次全量備份,存儲的是內存數據的二進制序列化形式,存儲上非常緊湊。當進行快照持久化時,會開啓一個子進程專門負責快照持久化,子進程會擁有父進程的內存數據,父進程修改內存子進程不會反應出來,所以在快照持久化期間修改的數據不會被保存,可能丟失數據。

5、總結

  • bgsave命令執行過程中,只有fork子進程時會阻塞服務器;而對於save命令,整個過程都會阻塞服務器;因此save已基本被廢棄,線上環境要杜絕save的使用;

2.AOF機制

  • 由於快照方式是在一定間隔時間做一次的,所以如果redis 意外down 掉的話,就會丟失最後一次快照後的所有修改。如果應用要求不能丟失任何修改的話,可以採用aof 持久化方式。
  • RDB文件保存的是數據庫的鍵值對數據,AOF保存的s是數據庫執行的寫命令。
  • Append-only file:aof 比快照方式有更好的持久化性,是由於在使用aof 持久化方式時,redis 會將每一個收到的寫命令都通過write 函數追加到文件中(默認是appendonly.aof)。當redis 重啓時會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。
  • AOF的實現流程有三步:
    • append->write->fsync
    • append追加命令到AOF緩衝區,write將緩衝區的內容寫入到程序緩衝區,fsync將程序緩衝區的內容寫入到文件

1、持久化原理

  • 他的原理看下面這張圖:

在這裏插入圖片描述

  • 每當有一個寫命令過來時,就直接保存在我們的AOF文件中。

2.文件重寫原理

  • AOF的方式也同時帶來了另一個問題。 AOF持久化模式每個寫命令都會追加到AOF文件,隨着服務器不斷運行,AOF文件會越來越大,爲了避免AOF產生的文件太大,服務器會對AOF文件進行重寫,將操作相同key的相同命令合併,從而減少文件的大小。

  • 舉個例子,要保存一個員工的名字、性別等信息:

    > hset employee_12345 name "hoohack"
    > hset employee_12345 good_at "php"
    > hset employee_12345 gender "male"
    
  • 只是錄入這個哈希鍵的狀態,AOF文件就需要保存三條命令,如果還有其他,比如刪除,或者更新值的操作,那命令將會更多,文件會更大,有了重寫後,就可以適當地減少文件的大小。

  • AOF重寫的實現原理是先服務器中的數據庫,然後遍歷數據庫,找出每個數據庫中的所有鍵對象,獲取鍵值對的鍵和值,根據鍵的類型對鍵值對進行重寫。比如上面的例子,可以合併爲下面的一條命令:

    > hset employee_12345 name "hoohack" good_at "php" gender "male"。
    
  • AOF的重寫會執行大量的寫入操作,Redis是單線程的,所以如果有服務器直接調用重寫,服務器就不能處理其他命令了,因此Redis服務器新起了單獨一個進程來執行AOF重寫。

  • Redis執行重寫的流程:
    在這裏插入圖片描述

  • 在子進程執行AOF重寫時,服務端接收到客戶端的命令之後,先執行客戶端發來的命令,然後將執行後的寫命令追加到AOF緩衝區中,同時將執行後的寫命令追加到AOF重寫緩衝區中。
    等到子進程完成了重寫工作後,會發一個完成的信號給服務器,服務器就將AOF重寫緩衝區中的所有內容追加到AOF文件中,然後原子性地覆蓋現有的AOF文件。

3. AOF也有三種觸發機制

  • appendonly yes //啓用 aof 持久化方式
    • appendfsync always // 同步持久化,收到寫命令就立即寫入磁盤,性能較差但數據完整性比較好
    • appendfsync everysec // 異步操作,每秒鐘寫入磁盤一次,在性能和持久化方面做了很好的折中。但是如果一秒內宕機,有數據丟失
    • appendfsync no //完全依賴 os,性能最好,持久化沒保證,從不同步

4.AOF機制的優勢與劣勢

  • 優勢:
    • AOF的持久化方式也是通過配置的不同,默認配置的是每秒同步,最快的模式是同步每一個命令,最壞的方式是等待系統執行fsync將緩衝同步到磁盤文件中,大部分操作系統是30s。通常情況下會配置爲每秒同步一次,所以最多會有1s的數據丟失
    • AOF日誌文件沒有任何磁盤尋址的開銷,寫入性能非常高,文件不容易破損
    • AOF日誌文件即使過大的時候,出現後臺重寫操作,也不會影響客戶端的讀寫。
    • AOF日誌文件的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。比如某人不小心用flushall命令清空了所有數據,只要這個時候後臺rewrite還沒有發生,那麼就可以立即拷貝AOF文件,將最後一條flushall命令給刪了,然後再將該AOF文件放回去,就可以通過恢復機制,自動恢復所有數據
  • 劣勢:
    • 對於同一份數據來說,AOF日誌文件通常比RDB數據快照文件更大
    • AOF開啓後,支持的寫QPS會比RDB支持的寫QPS低,因爲AOF一般會配置成每秒fsync一次日誌文件,當然,每秒一次fsync,性能也還是很高的

3.RDB和AOF該如何選擇

  • 不要僅僅使用RDB,因爲那樣會導致你丟失更多的數據
  • 也不要僅僅使用AOF,第一:通過AOF做冷備,沒有RDB做冷備恢復的速度快。第二:RDB每次簡單粗暴生成數據快照,更加健壯,可以避免AOF複雜的備份和恢復機制bug。(AOF的數據恢復速度沒有RDB來的快,RDB備份機制方便快捷)
  • 綜合使用AOF和RDB兩種持久化機制,使用AOF來保證數據不丟失,作爲數據恢復的第一選擇;用RDB做不同程度的冷備,當AOF備份文件丟失或損壞不可用時,可以使用RDB快照文件快速的恢復數據。

參考資料

redis持久化
詳解Redis中兩種持久化機制RDB和AOF(面試常問,工作常用)

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