持久化(Persistence),即把數據(如內存中的對象)保存到可永久保存的存儲設備中(如磁盤)。
持久化Redis全部數據保持在內存中,對數據的更新將異步地保存到磁盤上。redis
快照方式持久化就是在某時刻把全部數據進行完整備份。sql
例:Mysql的Dump方式、Redis的RDB方式。數據庫
寫日誌方式持久化就是把用戶執行的全部寫指令(增刪改)備份到文件中,還原數據時只須要把備份的全部指令從新執行一遍便可。安全
例:Mysql的Binlog、Redis的AOF、Hbase的HLog。服務器
RDB持久化方式可以在指定的時間間隔能對你的數據進行快照存儲。
在默認狀況下, Redis 將數據庫快照保存在名字爲 dump.rdb的二進制文件中。
在 Redis 運行時, RDB 程序將當前內存中的數據庫快照保存到磁盤文件中, 在 Redis 重啓動時, RDB 程序能夠經過載入 RDB 文件來還原數據庫的狀態。app
當 Redis 須要保存 dump.rdb 文件時, 服務器執行如下操做:異步
這種工做方式使得 Redis 能夠從寫時複製(copy-on-write)機制中獲益。工具
save
命令執行一個同步操做,以RDB文件的方式保存全部數據的快照。性能
127.0.0.1:6379> save OK
因爲 save
命令是同步命令,會佔用Redis的主進程。若Redis數據很是多時,save
命令執行速度會很是慢,阻塞全部客戶端的請求。
所以不多在生產環境直接使用SAVE 命令,可使用BGSAVE 命令代替。若是在BGSAVE命令的保存數據的子進程發生錯誤的時,用 SAVE命令保存最新的數據是最後的手段。優化
bgsave
命令執行一個異步操做,以RDB文件的方式保存全部數據的快照。
127.0.0.1:6379> bgsave Background saving started
Redis使用Linux系統的fock()
生成一個子進程來將DB數據保存到磁盤,主進程繼續提供服務以供客戶端調用。
若是操做成功,能夠經過客戶端命令LASTSAVE來檢查操做結果。
save
與 bgsave
對比命令 | save | bgsave |
---|---|---|
IO類型 | 同步 | 異步 |
阻塞? | 是 | 是(阻塞發生在fock(),一般很是快) |
複雜度 | O(n) | O(n) |
優勢 | 不會消耗額外的內存 | 不阻塞客戶端命令 |
缺點 | 阻塞客戶端命令 | 須要fock子進程,消耗內存 |
除了手動執行 save
和 bgsave
命令實現RDB持久化之外,Redis還提供了自動自動生成RDB的方式。
你能夠經過配置文件對 Redis 進行設置, 讓它在「 N 秒內數據集至少有 M 個改動」這一條件被知足時, 自動進行數據集保存操做。
好比說, 如下設置會讓 Redis 在知足「 60 秒內有至少有 1000 個鍵被改動」這一條件時, 自動進行數據集保存操做:
save 60 1000
# RDB自動持久化規則 # 當 900 秒內有至少有 1 個鍵被改動時,自動進行數據集保存操做 save 900 1 # 當 300 秒內有至少有 10 個鍵被改動時,自動進行數據集保存操做 save 300 10 # 當 60 秒內有至少有 10000 個鍵被改動時,自動進行數據集保存操做 save 60 10000 # RDB持久化文件名 dbfilename dump-<port>.rdb # 數據持久化文件存儲目錄 dir /var/lib/redis # bgsave發生錯誤時是否中止寫入,一般爲yes stop-writes-on-bgsave-error yes # rdb文件是否使用壓縮格式 rdbcompression yes # 是否對rdb文件進行校驗和檢驗,一般爲yes rdbchecksum yes
快照功能(RDB)並非很是耐久(durable): 若是 Redis 由於某些緣由而形成故障停機, 那麼服務器將丟失最近寫入、且仍未保存到快照中的那些數據。 從 1.1 版本開始, Redis 增長了一種徹底耐久的持久化方式: AOF 持久化。
你能夠在配置文件中打開AOF方式:
appendonly yes
打開AOF後, 每當 Redis 執行一個改變數據集的命令時(好比 SET), 這個命令就會被追加到 AOF 文件的末尾。這樣的話, 當 Redis 從新啓時, 程序就能夠經過從新執行 AOF 文件中的命令來達到重建數據集的目的。
你能夠經過配置文件配置 Redis 多久纔將數據 fsync 到磁盤一次。
每次有新命令追加到 AOF 文件時就執行一次 fsync :很是慢,也很是安全。
每秒 fsync 一次:足夠快(和使用 RDB 持久化差很少),而且在故障時只會丟失 1 秒鐘的數據。
推薦(而且也是默認)的措施爲每秒 fsync 一次, 這種 fsync 策略能夠兼顧速度和安全性。
從不 fsync :將數據交給操做系統來處理,由操做系統來決定何時同步數據。更快,也更不安全的選擇。
命令 | 優勢 | 缺點 |
---|---|---|
always | 不丟失數據 | IO開銷大,通常SATA磁盤只有幾百TPS |
everysec | 每秒進行與fsync,最多丟失1秒數據 | 可能丟失1秒數據 |
no | 不用管 | 不可控 |
推薦(而且也是默認)的措施爲每秒 fsync 一次, 這種 fsync 策略能夠兼顧速度和安全性。
由於 AOF 的運做方式是不斷地將命令追加到文件的末尾, 因此隨着寫入命令的不斷增長, AOF 文件的體積也會變得愈來愈大。舉個例子, 若是你對一個計數器調用了 100 次 INCR , 那麼僅僅是爲了保存這個計數器的當前值, AOF 文件就須要使用 100 條記錄(entry)。然而在實際上, 只使用一條 SET 命令已經足以保存計數器的當前值了, 其他 99 條記錄實際上都是多餘的。
爲了處理這種狀況, Redis 支持一種有趣的特性: 能夠在不打斷服務客戶端的狀況下, 對 AOF 文件進行重建(rebuild)。執行 bgrewriteaof 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數據集所需的最少命令。
Redis 2.2 須要本身手動執行 bgrewriteaof 命令; Redis 2.4 則能夠經過配置自動觸發 AOF 重寫。
bgrewriteaof 命令
Redis bgrewriteaof 命令用於異步執行一個 AOF(AppendOnly File)文件重寫操做。重寫會建立一個當前AOF文件的體積優化版本。
即便 bgrewriteaof 執行失敗,也不會有任何數據丟失,由於舊的AOF文件在 bgrewriteaof 成功以前不會被修改。
AOF 重寫由 Redis 自行觸發,bgrewriteaof 僅僅用於手動觸發重寫操做。
具體內容:
配置名 | 含義 |
---|---|
auto-aof-rewrite-min-size | 觸發AOF文件執行重寫的最小尺寸 |
auto-aof-rewrite-percentage | 觸發AOF文件執行重寫的增加率 |
統計名 | 含義 |
---|---|
aof_current_size | AOF文件當前尺寸(字節) |
aof_base_size | AOF文件上次啓動和重寫時的尺寸(字節) |
AOF重寫自動觸發機制,須要同時知足下面兩個條件:
- aof_current_size > auto-aof-rewrite-min-size
- (aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage
假設 Redis 的配置項爲:
auto-aof-rewrite-min-size 64mb auto-aof-rewrite-percentage 100
當AOF文件的體積大於64Mb,而且AOF文件的體積比上一次重寫之久的體積大了至少一倍(100%)時,Redis將執行 bgrewriteaof 命令進行重寫。
# 開啓AOF持久化方式 appendonly yes # AOF持久化文件名 appendfilename appendonly-<port>.aof # 每秒把緩衝區的數據同步到磁盤 appendfsync everysec # 數據持久化文件存儲目錄 dir /var/lib/redis # 是否在執行重寫時不一樣步數據到AOF文件 # 這裏的 yes,就是執行重寫時不一樣步數據到AOF文件 no-appendfsync-on-rewrite yes # 觸發AOF文件執行重寫的最小尺寸 auto-aof-rewrite-min-size 64mb # 觸發AOF文件執行重寫的增加率 auto-aof-rewrite-percentage 100
- | RDB | AOF |
---|---|---|
啓動優先級 | 低 | 高 |
體積 | 小 | 大 |
恢復速度 | 快 | 慢 |
數據安全性 | 丟數據 | 根據策略決定 |
通常來講, 若是想達到足以媲美 PostgreSQL 的數據安全性, 你應該同時使用兩種持久化功能。
若是你很是關心你的數據, 但仍然能夠承受數分鐘之內的數據丟失, 那麼你能夠只使用 RDB 持久化。
有不少用戶都只使用 AOF 持久化, 但並不推薦這種方式: 由於定時生成 RDB 快照(snapshot)很是便於進行數據庫備份, 而且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。