Redis持久化機制(AOF和RDB)

不少時候咱們須要持久化數據也就是將內存中的數據寫入磁盤裏面,大部分緣由是爲了以後重用數據(好比重啓機器、機器故障以後恢復數據),或者是爲了防止系統故障而將數據備份到一個遠程位置。redis

Redis不一樣於Memcached的很重要一點就是,Redisz支持持久化,並且支持兩種不一樣的持久化操做,Redis的一種持久化方式叫作快照(Snapshotting,RDB),另外一種方式只追加文件(append-only file,AOF).這兩種方法各有千秋,下面將介紹咱們爲何須要持久化,這兩種持久化的方法是什麼,怎麼用,如何選擇適合本身的持久化方法。數據庫

爲何須要持久化

Redis做爲一個鍵值對內存數據庫(NoSQL),數據都存儲在內存中,在處理客戶端請求時,全部操做都在內存當中進行,以下所示: 緩存

這樣作有什麼問題呢?安全

其實,只要稍微有點計算機基礎知識的人都知道,存儲在內存當中的數據,只要服務器關機(各類緣由引發),內存中的數據就會消失了,不只服務器關機會形成數據消失,Redis服務器守護進程退出,內存中的數據也同樣會消失。bash

對於只把Redis當緩存來用的項目來講,數據消失或許問題不大,從新從數據源把數據加載進來就能夠了,但若是直接把用戶提交的業務數據存儲在Redis中,把Redis做爲數據庫來使用,在其存儲重要業務數據,那麼Redis的內存數據丟失所形成的影響也許是毀滅性的。服務器

爲了不內存中數據丟失,Redis提供了持久化的支持,咱們能夠選擇不一樣的方式將數據從內存中保存到硬盤中,將數據持久化保存。app

所以Redis提供了RDB和AOF兩種不一樣的數據持久化方式。

RDB

RDB是一種快照存儲持久化方式,具體就是將Redis某一時刻的內存數據保存到硬盤裏的文件當中,默認保存的文件名爲dump.rdb,而在Redis服務器啓動時,會從新加載dump.rdb文件的數據到內存中恢復數據。異步

開啓RDB持久化方式

開啓RDB持久方方式很簡單,客戶端能夠經過向Redis服務器發送save或bgsave命令讓服務器生成rdb文件,或者經過服務器配置文件指定觸發RDB條件。post

一、save命令

save命令是一個同步操做性能

# 同步數據到磁盤上
> save
複製代碼
save 900 1           #在900秒(15分鐘)以後,若是至少有1個key發生變化,Redis就會自動觸發BGSAVE命令建立快照。

save 300 10          #在300秒(5分鐘)以後,若是至少有10個key發生變化,Redis就會自動觸發BGSAVE命令建立快照。

save 60 10000        #在60秒(1分鐘)以後,若是至少有10000個key發生變化,Redis就會自動觸發BGSAVE命令建立快照。
複製代碼

當客戶端向服務器發送save命令請求進行持久化時,服務器會阻塞save命令以後的其餘客戶端的請求,直到數據同步完成。

若是數據量太大,同步數據會執行好久,而這期間Redis服務器也沒法接收其餘請求,因此,最好不要在生產環境使用save命令。

二、bgsave

與save命令不一樣,bgsave命令是一個異步操做。

# 異步保存數據集到磁盤上
> bgsave
複製代碼

當客戶端發出bgsave命令時,Redis服務器主進程會forks一個子進程來數據同步問題,在數據保存到rdb文件以後,子進程會退出。

全部,與save命令相比,Redis服務器在處理bgsave採用子進程進行IO寫入,而主進程仍然能夠接收其餘請求,但forks子進程是同步的,全部forks子進程時,同樣不能接收其餘請求,這意味着,若是forks一個子進程話費的時間過久(通常很快),bgsave命令任然有阻塞其餘客戶的請求的狀況發生。

三、服務器配置自動觸發

除了經過客戶端發送命令外,還有一種方式,就是在Redis配置文件中的save指定到達觸發RDB持久化的條件,好比多少秒內至少達到多少寫操做就開啓RDB數據同步。

例如咱們能夠在配置文件redis.conf指定以下的選項:

# 900s內至少達到一條寫命令
save 900 1
# 300s內至少達至10條寫命令
save 300 10
# 60s內至少達到10000條寫命令
save 60 10000
複製代碼

以後在啓動服務器時加載配置文件

# 啓動服務器加載配置文件
redis-server redis.conf

複製代碼

這種童工服務器配置文件觸發RDB的方式,與bgsave命令相似,達到觸發條件時,會forks一個子進程進行數據同步,不過最好不要經過這種方式觸發RDB持久化,由於設置觸發的時間過短,則容易頻繁寫入rdb文件,影響服務器性能,時間設置太長則會形成數據丟失。

四、rdb文件

前面介紹了三種讓服務器生成rdb文件的方式,不管是由主進程生成仍是子進程來生成,其過程以下:

  • 一、生成臨時rdb文件,並寫入數據。
  • 二、完成數據寫入,用臨時文件代替正式rdb文件。
  • 三、刪除原來的db文件
# 是否壓縮rdb文件
rdbcompression yes

# rdb文件的名稱
dbfilename redis-6379.rdb

# rdb文件保存目錄
dir ~/redis/
複製代碼

五、RDB的幾個優勢

  • 一、與AOF方式相比,經過rdb文件恢復數據比較快。
  • 二、rdb文件很是經湊,適合於數據備份。
  • 三、經過RDB進行數據備份,因爲使用子進程生成,因此對Redis服務器性能影響較小。

六、RDB的幾個缺點

  • 一、若是服務器宕機的話,採用RDB的方式會形成某個時間段內數據的丟失,好比咱們設置10分鐘同步一次或5分鐘達到1000次寫入就同步一次,那麼若是還沒達到觸發條件服務器就死機了,那麼這個時間段的數據會丟失。
  • 使用save命令會形成服務器阻塞,直接數據同步完成才能接收後續請求。
  • 使用bgsave命令在forks子進程時,若是數據量太大,forks的過程業務發生阻塞,另外,forks子進程會消耗內存。

AOF

與RDB存儲某個時刻的快照不一樣,AOF持久化方式會記錄客戶端對服務器的每一次寫操做命令,並將這些寫操做以Redis協議追加保存到之後綴爲aof文件末尾,在Redis服務器重啓時,會加載並運行aof文件的命令,以達到恢復數據的目的。

開啓AOF持久化方式

Redis默認不開啓AOF持久化方式,咱們能夠在配置文件中開啓並進行更加詳細的配置,以下面的redis.conf文件:

# 開啓aof機制
appendonly yes

# aof文件名
appendfilename "appendonly.aof"

# 寫入策略,always表示每一個寫操做都保存到aof文件中,也能夠是everysec或no
appendfsync always

# 默認不重寫aof文件
no-appendfsync-on-rewrite no

# 保存目錄
dir ~/redis/

複製代碼

三種寫入策略

在上面的配置文件中,咱們能夠經過appendfsync選項指定寫入策略,有三個選項

appendfsync always
# appendfsync everysec
# appendfsync no

複製代碼

一、always

客戶端的每個寫操做都保存到aof文檔中,這種策略很安全,可是每一個寫請求都有IO操做,因此也很慢。

二、everysec

appendfsync的默認策略,每秒寫入一次aof文件,所以,不少可能會丟失1s的數據。

三、no

Redis服務器不負責寫入aof,而是交由操做系統來處理何時寫入aof文件。更快,但也最不安全的選擇,不推薦使用

AOF文件重寫

AOF將客戶端的每個寫操做都追加到aof文件末尾,好比對一個key屢次執行incr命令,這時候,aof保存每一次命令道aof文件中,aof文件會變得很是大。

incr num 1
incr num 2
incr num 3
incr num 4
incr num 5
incr num 6
...
incr num 100000

複製代碼

aof文件太大,加載aof文件恢復數據時,就會很是慢,爲了解決這個問題,Redis支持aof文件重寫,經過重寫aof,能夠生成一個恢復當前數據的最少命令集,好比上面的例子中那麼多命令,能夠重寫爲:

set num 100000
複製代碼

aof文件是一個二進制文件,並非像上面的例子同樣,直接保存每一個命令,而使用Redis本身的格式,上面只是方便演示

兩種寫入方式

經過在redis.conf配置文件中的選項no-appendfsync-on-rewrite能夠設置是否開啓重寫,這種方式會在每次fsync時都重寫,影響服務器性能,所以默認值爲no,不推薦使用。

#默認不重寫aof文件
no-appendfsync-no-rewrite no
複製代碼

客戶端向服務器發送bgrewriteaof命令,也可讓服務器進行AOF重寫。

#讓服務器異步重寫追加aof文件命令
> bgrewriteaof
複製代碼

AOF重寫方式也是異步操做,即若是要寫入aof文件,則Redis主進程會forks一個子進程來處理

重寫aof文件的好處

  • 壓縮aof文件,減小磁盤佔用量。
  • 將aof的命令壓縮爲最小命令集,加快了數據恢復的速度

AOF文件損壞

在寫入aof日誌文件時,若是Redis服務器宕機,則aof日誌文件會處格式錯誤,在重啓Redis服務器時,Redis服務器會拒絕載入這個aof文件,能夠經過如下步驟修復aof並恢復數據。

  • 備份現有的aof文件,以防萬一
  • 使用redis-check-aof命令修復aof文件,該命令格式以下:
#修復aof日誌文件
$ redis-check-aof -fix file.aof
複製代碼
  • 重啓Redis服務器,架子啊已經修復的aof文件,恢復數據。

AOF優勢

AOF只是追加日誌文件,所以對服務器性能影響較小,速度比RDB要快,消耗的內存較少。

AOF的缺點

  • AOF方式生成的日誌文件太大,即便經過AOF重寫,文件體積依然很大
  • 恢復數據的速度比RDB慢。

選擇RDB仍是AOF

經過上面的比較,我麼瞭解了RDB和AOF的各自的優勢和缺點,到底如何選擇呢? 經過下面的對比,咱們能夠從幾個方面對比一下AOF和RDB,在應用時要根據本身的實際需求,選擇RDB或者AOF,其實,若是想要數據足夠安全,能夠兩種方式都開啓,但兩種持久化方式同時進行IO操做,會嚴重影響服務器性能,所以有時候不得不作出選擇。

當RDB和AOF兩種方式都開啓時,Redis會優先選擇使用AOF日誌恢復數據,所以AOF保存的文件比RDB文件更加完整

Redis 4.0 對於持久化機制的優化

Redis 4.0 開始支持 RDB 和 AOF 的混合持久化(默認關閉,能夠經過配置項 aof-use-rdb-preamble 開啓)。

若是把混合持久化打開,AOF 重寫的時候就直接把 RDB 的內容寫到 AOF 文件開頭。這樣作的好處是能夠結合 RDB 和 AOF 的優勢, 快速加載同時避免丟失過多的數據。固然缺點也是有的, AOF 裏面的 RDB 部分就是壓縮格式再也不是 AOF 格式,可讀性較差。

以上文章主要來自10分鐘完全理解Redis的持久化機制:RDB和AOF

相關文章
相關標籤/搜索