Redis 是使用很是普遍的 Key-Value 內存數據庫。由於數據都存放在內存中,因此存取速度很是快。不過,不少狀況下咱們須要將 Redis 中的數據保存到硬盤中以便作備份。Redis 提供了兩種數據持久化方式,分別是 RDB 和 AOP,本文分析這兩種方式的使用以及過時鍵對持久化的影響。數據庫
RDB 指的是將 Redis 數據庫在某個時間點的快照保存到磁盤,所生成的 RDB 文件是一個通過壓縮的二進制文件,經過這個文件能夠還原出 Redis 的數據狀態。安全
建立快照的方式有如下幾種:服務器
BGSAVE
命令,Redis 會調用 fork 建立一個子進程,而後子進程負責將快照寫入硬盤,而父進程繼續處理命令請求。SAVE
命令,此時 Redis 將開始建立快照,而且在完成以前再也不響應其它命令。save 60 10000
,那麼從 Redis 最近一次建立快照算起,當 「60 秒內有 10000 次寫入」 這個條件被知足時, Redis 就會自動觸發 BGSAVE
命令。若是用戶設置了多個 save 配置選項,那麼當任意一個 save 配置知足時,Redis 就會觸發一次 BGSAVE
命令。save 配置的格式以下所示:save 60 10000 stop-writes-on-bgsave-error no rdbcompression yes // 使用壓縮 dbfilename dump.rdb // RBD 文件的名字 dir ./
SHUTDOWN
命令接收到關閉服務器的請求時,或者接收到 TERM命令時,會執行一個 SAVE
命令,而且阻塞全部的客戶端,再也不執行任何請求。在 SAVE
命令執行結束後關閉服務器。SYNC
命令來開始一次複製操做的時候,若是主服務器沒有在執行 BGSAVE
操做,或者主服務器並不是剛執行完 BGSAVE
,那麼主服務器會執行 BGSAVE
命令。RDB 的主要問題是,若是系統發生崩潰,那麼最近一次執行完快照後修改的數據將被丟失。所以,RDB 適合用於即便丟失一部分數據也不會形成影響的應用程序。app
AOF 指的是將全部執行的寫命令寫到 AOF 文件的末尾,以此來記錄數據發生的變化。若是 Redis 想要恢復 AOF 中的數據,只要從新執行一次 AOF 文件中所包含的寫命令就能夠。性能
AOF 的配置以下所示:學習
appendonly yes // 打開 aof appendfsync everysec // aof 同步的頻率 no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 // 文件大小增加比超過這個值開始自動重寫 aof auto-aof-rewrite-min-size 64mb // 文件大小超過這個值才能夠有可能自動重寫 aof
上面的配置中,appendfsync everysec
設置的是同步的頻率。應用程序在向硬盤寫入數據的時候有 3 個步驟:操作系統
file.write()
向文件寫入,此時須要寫入的內容被存儲到了緩衝區,並非真正寫到硬盤上了。操做系統使用以上的文件寫入方式是爲了提升性能,畢竟硬盤 I/O 操做是比較耗時的。可是,這種方式的缺點在於若是機器崩潰了那麼緩衝區的內容將丟失。程序可使用 file.flush()
來請求操做系統儘快地將緩衝區的內容刷新到硬盤上,不過什麼時候開始執行仍然由操做系統決定。程序也能夠命令操做系統將文件同步 ( sync ) 到硬盤,同步操做會阻塞應用程序直到數據被寫入硬盤。當同步操做完成後,即便系統出現故障,也不會對被同步的文件形成影響。設計
對於 Redis 來說,能夠指定 appendfsync
以何種方式讓數據徹底同步到硬盤,這個配置有 3 個選項:code
always
可使得在 Redis 發生崩潰時丟失的數據最少,可是也是最消耗性能的,致使 Redis 的處理速度變慢。ererysec
是一種兼顧性能與數據安全的方式,在這種狀況下,若是系統崩潰,用戶最多會丟失一秒內的數據。no
選項徹底將同步交給操做系統被決定,性能也不比 everysec
高多少,是不推薦的方式。進程
AOF 的缺點是隨着 Redis 的不斷運行,AOF 文件可能會很是大,甚至用完硬盤的空間。解決這個問題的辦法是 AOF 重寫。
客戶端能夠發送 BGREWRITEAOF
命令讓 Redis 重寫 AOF 文件,Redis 會移除冗餘的 AOF 命令進行重寫,使得 AOF 文件的體積儘量地小。
除了客戶端主動發送 BGREWRITEAOF
命令,也可使用配置讓 Redis 在知足必定條件地狀況下自動開始重寫 AOF 文件。例如上一小節設置了 auto-aof-rewrite-percentage 100
和 auto-aof-rewrite-min-size 64mb
。這兩個配置的含義是,若是 AOF 文件大於 64MB 而且比上一次重寫以後的大小增長了一倍的時候,Redis 將執行 BGREWERITEAOF
命令。
用戶每每爲 Redis 中的鍵設定過時時間,所以須要必定的策略來刪除過時鍵,能夠有三種策略:
從上面 3 種策略能夠看出,單用第一個確定是不行的,Redis 的響應時間相當重要。第二個則是比較好的方式,在獲取鍵的時候判斷是否過時並決定是否刪除,它的缺點是不少鍵沒法及時刪除。若是一個過時鍵再也沒有被訪問,那麼它將永遠留在內存中,而第三種方式正好能夠彌補。
Redis 中過時鍵的刪除策略正是惰性刪除與按期刪除的結合。
瞭解了過時鍵的刪除策略後,下面看下鍵的過時時間對持久化的影響。
在生成 RDB 文件的過程當中,若是一個鍵已通過期,那麼其不會被保存到 RDB 文件中。在載入 RDB 的時候,要分兩種狀況:
對於 AOF 來講,若是一個鍵過時了,那麼不會馬上對 AOF 文件形成影響。由於 Redis 使用的是惰性刪除和按期刪除,只有這個鍵被刪除了,纔會往 AOF 文件中追加一條 DEL 命令。在重寫 AOF 的過程當中,程序會檢查數據庫中的鍵,已通過期的鍵不會被保存到 AOF 文件中。
在運行過程當中,對於主從複製的 Redis,主服務器和從服務器對於過時鍵的處理也不相同:
這麼作的主要目的是保證數據一致性,因此當一個過時鍵存在於主服務器時,也必然存在於從服務器。
本文對 Redis 的兩種持久化方式進行了簡要的梳理,分析了 Redis 刪除過時鍵的策略以及對持久化的影響。理解了這部份內容不只可讓咱們對 Redis 的使用更加駕輕就熟,對於學習 Redis 的其它內容如複製的過程也會頗有幫助。
參考
若是個人文章對您有幫助,不妨點個贊支持一下(^_^)