Redis持久化之RDB&&AOF的區別


在說Redis持久化之前,需要搞明白什么是數據庫狀態這個概念,因為持久化的就是將內存中的數據庫狀態保存到磁盤上。那么什么是數據庫狀態呢?Redis是一個key-value數據庫服務器,一般默認是有16個數據庫,可以使用select <index>命令進行切換(0-15),這每個非空的數據庫又可以包含任意多個鍵值對,為了方便起見,我們將數據庫服務器中的非空數據庫以及它們的鍵值對通常為【數據庫狀態】,所以這里持久化,說的不是一個數據庫,而是服務器上的所有非空數據庫。

接着,我們繼續來說redis的兩種持久化方式,一種是RDB持久化,一種是AOF持久化,這兩種持久化方式都可以將內存中的數據庫狀態保存到磁盤上,但是原理非常不同,我們逐一來看看,首先說一下RDB持久化。

RDB持久化默認生成的文件名為dump.rdb,這個可以通過配置文件配置,RDB文件一個經過壓縮的二進制文件,接下來介紹一些rdb文件結構,RDB文件包含五個部分,分別是【Redis |  db_version  |  databases | EOF | check_sum】開頭的Redis表示這是一個RDB文件,服務器可以通過這個快速檢查載入的文件是否是rdb文件,db_version是一個整數,代表RDB文件的版本,databases部分包含0個或者是任意多個數據庫,以及數據庫中的鍵值對數據,如果數據庫狀態是空,那么這部分也是空的,這部分的結構如下【SELECTDB | db_number | key_values_pairs】其中SELECTDB是一個常量,長度是一字節,當服務器遇到這個的時候,知道接下來要讀入的將是一個數據庫號碼,db_number中保存的是一個數據庫號碼(0-15)這兩部分結合就可以切換到相應的數據庫,然后讀取鍵值對了,鍵值對的部分的結構有兩種,一種是帶過期值的,一種是不帶過期值的,如果是帶過期值,那么結構是【EXPIRETIME_MS | ms |  TYPE | key | value】第一個常量和SELECTDB一樣,第二部分是毫秒為單位的UNIX時間戳,就是鍵值對的過期時間,然后是TYPE記錄了value的類型,是String,list,set,zset,hash,等。不帶過期值的鍵值對部分的結構沒有前兩部分,只是【TYPE | key | value】

RDB持久化可以通過命令進行手動執行,也可以配置好后讓服務器自動執行,手動執行可以使用Redis命令【SAVE】或者【BGSAVE】,這兩個命令有一些差別,需要說明一下,save命令會阻塞服務器進程,也就說,但save命令執行的時候服務器不能夠處理任何命令請求,知道save命令執行完畢,RDB文件創建完畢,bgsave命令不會阻塞服務器,而是通過派生出一個子進程,然后由子進程負責創建RDB文件,服務器進程繼續處理命令請求,這里需要說明一下,bgsave處理期間,服務器進程雖然能夠繼續處理命令請求,但是save,bgsave,bgrewriteaof這三個命令的處理方式會和平時有所不同,在bgsave期間,save命令會被服務器拒絕,服務器禁止save和bgsave同時執行,避免父進程和子進程同時執行兩個rdbSave(創建RDB文件的實際工作實際上是由rdbSave函數完成,save和bgsave都會調用這個函數,只是調用的方式不同)調用,bgsave命令在bgsave期間也會被拒絕,理由和拒絕save的理由一樣,兩個bgsave也會產生競爭,bgrewriteaof命令會被延遲到bgsave執行完畢之后執行。

Redis沒有專門的RDB文件載入命令,只要Redis服務器開啟,就會檢測RDB文件是否存在,就會自動載入RDB文件,這里需要說明一點,如果服務器開啟了AOF持久化功能,服務器會優先使用AOF文件來還原數據庫狀態,只有在AOF持久化功能關閉的時候,才會使用RDB文件來還原數據庫狀態。

接下來說一下,RDB自動保存,前面已經說了,RDB可以通過手動執行,SAVE命令和BGSAVE命令,也可以通過配置讓服務器自動執行,那么如何配置呢?

Redis.conf中可以配置,默認配置如下:

 save 900 1
save 300 10
save 60 10000

以上表示的意思是,

  • 900秒之內對服務進行了至少一次修改
  • 300秒之內服務器進行了至少10次修改
  • 60秒之內對服務器進行了至少10000次修改。

這些條件滿足其中的任意一個bgsave命令就會自動執行。

那么你可能會好奇,服務器是怎么知道我做了多少修改的?服務器中有個dirty計數器和一個lastsave時間戳

當服務器執行一個數據庫修改命令之后,dirty計數器就會進行更新,命令修改了多少次數據庫,dirty就會增加多少,如:【set msg  hello】修改了一個,那么dirty就加一,如果【mset msg word name nihao age 20】那么dirty就增加三

lastsave屬性記錄上次服務器執行保存操作的時間,是一個unix時間戳,通過這兩個屬性,可以很簡單的距離上次保存已經多少時間了,以及修改了多少次數據庫,一旦滿足以上三個條件,那么就自動調用bgsave命令,同時更新lastsave屬性和dirty屬性歸零。

至於檢查保存條件是否滿足這個工作,是由Redis服務器周期性操作函數serverCron默認間隔100毫秒執行一次檢查,這個函數有很多地方用到,注意一下,這個函數是對正在運行的服務器進行維護的函數,在Redis事件中會有提到(Redis服務器是一個事件驅動程序,什么是事件驅動呢?就是發生事件的時候才會動一下,不然就跟死了一樣,事件驅動又分為文件事件和時間事件,ServerCron就是一種時間驅動,至於文件驅動,其實就是客戶端發過來一個命令,服務器才會去執行,然后給客戶端返回結果)

最后說一點,Redis本身自帶了一個RDB文件檢查工具redis-check-dump,可以使用這個工具對rdb文件是否完整進行檢查

 

【文章來源:http://www.linuxidc.com/Linux/2015-07/120733.htm】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM