Redis最常用的場景就是做緩存,把DB資料存儲在記憶體,然後直接從記憶體讀資料,這樣系統響應就會很快。
風險是一旦伺服器當機,記憶體中資料将全部丢失。
最簡單的解決方案是從後端DB恢複這些資料,但注意:
- 需要頻繁通路DB,會給DB帶來巨大壓力
- 這些資料是從慢速DB中讀出來的,性能肯定比不上從Redis中讀取,導緻使用這些資料的應用程式響應變慢。
是以,對于Redis,實作資料持久化,避免從後端 DB進行恢複,很關鍵。
1 持久化概論
1.1 什麼是持久化
redis所有資料儲存在記憶體,對資料的更新将異步儲存到磁盤。
持久化的意義:
主要是做災難恢複、資料恢複,可歸類到高可用。
比如你的Redis當機,你要做的事情是讓Redis變得可用,盡快變得可用!
重新開機Redis,盡快讓它對外提供服務,若你沒做資料備份,即使Redis啟動了,資料都沒了!有啥可用的?
而且很可能,大量請求過來,緩存全部無法命中,造成緩存雪崩。然後MySQL當機,你都沒法去找資料恢複到Redis裡面去,Redis的資料從哪兒來?就是從MySQL來的!
若把Redis的持久化做好,備份和恢複方案也做到,那麼即使你的Redis故障,也可通過備份資料,快速恢複,一旦恢複立即對外提供服務。
1.2 資料庫持久化政策
資料庫不關心故障
而是在資料檔案損壞後從資料備份或快照中恢複
RDB 就是這種情況
資料庫使用記錄檔記錄每個操作的操作行為
以在失敗後通過日志恢複一緻性。由于記錄檔是按順序追加寫入的,是以不會出現無法恢複記錄檔的情況
類似于 Mysql 的重做和撤消日志。
資料庫不修改舊資料,而僅通過追加進行寫入
是以資料本身就是日志,是以永遠不會出現資料無法恢複的情況
CouchDB 是一個很好的例子。AOF 類似這種情況
1.2 持久化方式
RDB - 快照
按指定時間間隔執行資料集的時間點快照存儲,類似于MySQL Dump的 frm 備份檔案。
在Redis内部一個定時器事件,每隔固定時間去檢查目前資料發生的改變次數與時間是否滿足配置的持久化觸發的條件,如果滿足則通過作業系統fork調用來建立出一個子程序,這個子程序預設會與父程序共享相同的位址空間,這時就可以通過子程序來周遊整個記憶體來進行存儲操作,而主程序則仍然可以提供服務,當有寫入時由作業系統按照記憶體頁(page)為機關來進行copy-on-write保證父子程序之間不會互相影響。
缺點是快照隻是代表一段時間内的記憶體映像,是以系統重新開機會丢失上次快照與重新開機之間所有的資料。
AOF - 指令日志
記錄每次對伺服器寫的操作,當伺服器重新開機的時候會重新執行這些指令來恢複原始的資料(MySQL 的 binlog)。
AOF 會記錄伺服器接收的每個寫操作,這些操作将在伺服器啟動時再次執行,以重建原始資料集。使用與Redis協定本身相同的格式記錄指令,并且僅采用append-only方式。當日志太大時,Redis可以在背景重寫日志。類似于MySQL Binlog、Hbase HLog。在Redis重新開機時,通過回放日志中的寫入指令來重構整個資料。
RDB與AOF混用
Redis4.0 開始的新特性。在混合使用中 AOF 讀取 RDB 資料重建原始資料集,集二者優勢為一體。
如果希望Redis僅作為純記憶體的緩存來用,亦可禁用RDB和AOF。
可以在同一執行個體中同時使用AOF和RDB。這種情況下,當Redis重新啟動時,AOF檔案将用于重建原始資料集,因為它可以保證是最完整的。
最重要的是了解RDB與AOF持久性之間的不同權衡。如果同時使用RDB和AOF兩種持久化機制,那麼在Redis重新開機時,會使用AOF來重新建構資料,因為AOF中的資料更加完整!