Redis做爲一個內存數據庫,數據是之內存爲載體存儲的,那麼一旦Redis服務器進程退出,服務器中的數據也會消失。爲了解決這個問題,Redis提供了持久化機制,也就是把內存中的數據保存到磁盤當中,避免數據意外丟失redis
Redis提供了兩種持久化方案:RDB持久化和AOF持久化,一個是快照的方式,一個是相似日誌追加的方式數據庫
RDB持久化是經過快照的方式,即在指定的時間間隔內將內存中的數據集快照寫入磁盤。在建立快照以後,用戶能夠備份該快照,能夠將快照複製到其餘服務器以建立相同數據的服務器副本,或者在重啓服務器後恢復數據。RDB是Redis默認的持久化方式緩存
RDB持久化會生成RDB文件,該文件是一個壓縮過的二進制文件,能夠經過該文件還原快照時的數據庫狀態,即生成該RDB文件時的服務器數據。RDB文件默認爲當前工做目錄下的dump.rdb
,能夠根據配置文件中的dbfilename
和dir
設置RDB的文件名和文件位置安全
# 設置 dump 的文件名 dbfilename dump.rdb # 工做目錄 # 例如上面的 dbfilename 只指定了文件名, # 可是它會寫入到這個目錄下。這個配置項必定是個目錄,而不能是文件名。 dir ./
觸發快照的時機bash
save
和bgsave
命令save <seconds> <changes>
規則,自動間隔性執行bgsave
命令bgsave
flushall
命令清空服務器數據shutdown
命令關閉Redis時,會執行save
命令執行save
和bgsave
命令,能夠手動觸發快照,生成RDB文件,二者的區別以下服務器
使用save
命令會阻塞Redis服務器進程,服務器進程在RDB文件建立完成以前是不能處理任何的命令請求app
127.0.0.1:6379> save OK
而使用bgsave
命令不一樣的是,basave
命令會fork
一個子進程,而後該子進程會負責建立RDB文件,而服務器進程會繼續處理命令請求async
127.0.0.1:6379> bgsave Background saving started
fork()
是由操做系統提供的函數,做用是建立當前進程的一個副本做爲子進程函數
fork
一個子進程,子進程會把數據集先寫入臨時文件,寫入成功以後,再替換以前的RDB文件,用二進制壓縮存儲,這樣能夠保證RDB文件始終存儲的是完整的持久化內容性能
在配置文件中設置save <seconds> <changes>
規則,能夠自動間隔性執行bgsave
命令
################################ SNAPSHOTTING ################################ # # Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # # Note: you can disable saving completely by commenting out all "save" lines. # # It is also possible to remove all the previously configured save # points by adding a save directive with a single empty string argument # like in the following example: # # save "" save 900 1 save 300 10 save 60 10000
save <seconds> <changes>
表示在seconds秒內,至少有changes次變化,就會自動觸發gbsave
命令
save 900 1
當時間到900秒時,若是至少有1個key發生變化,就會自動觸發bgsave
命令建立快照save 300 10
當時間到300秒時,若是至少有10個key發生變化,就會自動觸發bgsave
命令建立快照save 60 10000
當時間到60秒時,若是至少有10000個key發生變化,就會自動觸發bgsave
命令建立快照除了RDB持久化,Redis還提供了AOF(Append Only File)持久化功能,AOF持久化會把被執行的寫命令寫到AOF文件的末尾,記錄數據的變化。默認狀況下,Redis是沒有開啓AOF持久化的,開啓後,每執行一條更改Redis數據的命令,都會把該命令追加到AOF文件中,這是會下降Redis的性能,但大部分狀況下這個影響是可以接受的,另外使用較快的硬盤能夠提升AOF的性能
能夠經過配置redis.conf
文件開啓AOF持久化,關於AOF的配置以下
# appendonly參數開啓AOF持久化 appendonly no # AOF持久化的文件名,默認是appendonly.aof appendfilename "appendonly.aof" # AOF文件的保存位置和RDB文件的位置相同,都是經過dir參數設置的 dir ./ # 同步策略 # appendfsync always appendfsync everysec # appendfsync no # aof重寫期間是否同步 no-appendfsync-on-rewrite no # 重寫觸發配置 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 加載aof出錯如何處理 aof-load-truncated yes # 文件重寫策略 aof-rewrite-incremental-fsync yes
AOF須要記錄Redis的每一個寫命令,步驟爲:命令追加(append)、文件寫入(write)和文件同步(sync)
開啓AOF持久化功能後,服務器每執行一個寫命令,都會把該命令以協議格式先追加到aof_buf
緩存區的末尾,而不是直接寫入文件,避免每次有命令都直接寫入硬盤,減小硬盤IO次數
對於什麼時候把aof_buf
緩衝區的內容寫入保存在AOF文件中,Redis提供了多種策略
appendfsync always
:將aof_buf
緩衝區的全部內容寫入並同步到AOF文件,每一個寫命令同步寫入磁盤appendfsync everysec
:將aof_buf
緩存區的內容寫入AOF文件,每秒同步一次,該操做由一個線程專門負責appendfsync no
:將aof_buf
緩存區的內容寫入AOF文件,何時同步由操做系統來決定appendfsync
選項的默認配置爲everysec
,即每秒執行一次同步
關於AOF的同步策略是涉及到操做系統的write
函數和fsync
函數的,在《Redis設計與實現》中是這樣說明的
爲了提升文件寫入效率,在現代操做系統中,當用戶調用
write
函數,將一些數據寫入文件時,操做系統一般會將數據暫存到一個內存緩衝區裏,當緩衝區的空間被填滿或超過了指定時限後,才真正將緩衝區的數據寫入到磁盤裏。這樣的操做雖然提升了效率,但也爲數據寫入帶來了安全問題:若是計算機停機,內存緩衝區中的數據會丟失。爲此,系統提供了
fsync
、fdatasync
同步函數,能夠強制操做系統馬上將緩衝區中的數據寫入到硬盤裏,從而確保寫入數據的安全性。
從上面的介紹咱們知道,咱們寫入的數據,操做系統並不必定會立刻同步到磁盤,因此Redis才提供了appendfsync
的選項配置。當該選項時爲always
時,數據安全性是最高的,可是會對磁盤進行大量的寫入,Redis處理命令的速度會受到磁盤性能的限制;appendfsync everysec
選項則兼顧了數據安全和寫入性能,以每秒一次的頻率同步AOF文件,即使出現系統崩潰,最多隻會丟失一秒內產生的數據;若是是appendfsync no
選項,Redis不會對AOF文件執行同步操做,而是有操做系統決定什麼時候同步,不會對Redis的性能帶來影響,但假如系統崩潰,可能會丟失不定數量的數據
在瞭解AOF重寫以前,咱們先來看看AOF文件中存儲的內容是啥,先執行兩個寫操做
127.0.0.1:6379> set s1 hello OK 127.0.0.1:6379> set s2 world OK
而後咱們打開appendonly.aof
文件,能夠看到以下內容
*3 $3 set $2 s1 $5 hello *3 $3 set $2 s2 $5 world
該命令格式爲Redis的序列化協議(RESP)。
*3
表明這個命令有三個參數,$3
表示該參數長度爲3
看了上面的AOP文件的內容,咱們應該能想象,隨着時間的推移,Redis執行的寫命令會愈來愈多,AOF文件也會愈來愈大,過大的AOF文件可能會對Redis服務器形成影響,若是使用AOF文件來進行數據還原所需時間也會越長
時間長了,AOF文件中一般會有一些冗餘命令,好比:過時數據的命令、無效的命令(重複設置、刪除)、多個命令可合併爲一個命令(批處理命令)。因此AOF文件是有精簡壓縮的空間的
AOF重寫的目的就是減少AOF文件的體積,不過值得注意的是:AOF文件重寫並不須要對現有的AOF文件進行任何讀取、分享和寫入操做,而是經過讀取服務器當前的數據庫狀態來實現的
文件重寫可分爲手動觸發和自動觸發,手動觸發執行bgrewriteaof
命令,該命令的執行跟bgsave
觸發快照時相似的,都是先fork
一個子進程作具體的工做
127.0.0.1:6379> bgrewriteaof Background append only file rewriting started
自動觸發會根據auto-aof-rewrite-percentage
和auto-aof-rewrite-min-size 64mb
配置來自動執行bgrewriteaof
命令
# 表示當AOF文件的體積大於64MB,且AOF文件的體積比上一次重寫後的體積大了一倍(100%)時,會執行`bgrewriteaof`命令 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
下面看一下執行bgrewriteaof
命令,重寫的流程
fork
一個子進程來建立一個新的AOF文件aof_buf
的同時,還會追加到aof_rewrite_buf
AOF重寫緩衝區Redis4.0開始支持RDB和AOF的混合持久化(能夠經過配置項 aof-use-rdb-preamble
開啓)
redis-check-aof fix
命令修復上面介紹了RDB持久化和AOF持久化,那麼來看一下他們各自的優缺點以及該如何選擇持久化方案
關於RDB和AOF的優缺點,官網上面也給了比較詳細的說明https://redis.io/topics/persistence
RDB
優勢:
缺點:
AOF
優勢:
缺點:
若是是數據不那麼敏感,且能夠從其餘地方從新生成補回的,那麼能夠關閉持久化
若是是數據比較重要,不想再從其餘地方獲取,且能夠承受數分鐘的數據丟失,好比緩存等,那麼能夠只使用RDB
若是是用作內存數據庫,要使用Redis的持久化,建議是RDB和AOF都開啓,或者按期執行bgsave
作快照備份,RDB方式更適合作數據的備份,AOF能夠保證數據的不丟失