標籤:
redis持久化
redis的資料存在記憶體中,所以存取效能好。但是存在記憶體中的資料存在一個問題,一旦機器重啟,記憶體資料消失。為瞭解決這個問題,redis支援持久化。持久化就是為瞭解決記憶體資料丟失時恢複資料的,而不是為了將暫時不用的資料轉移到硬碟。
redis儲存資料達到記憶體上限時,再也存不進去資料的,會報錯。實際生產環境中,我們最好保證資料最大量不超過記憶體的上限的一半。這個理由後面會講到。
緩衝穿透:某個不存在的值被頻繁請求,緩衝不存在,請求資料庫,資料庫中也不存在,每次都去請求資料庫。
緩衝雪崩:所有的緩衝都失效了。
持久化可以理解為就是把記憶體資料副本存在硬碟中,這樣記憶體資料丟失時可以從硬碟中恢複。
redis支援兩種方式的持久化,RDB(記憶體快照)和AOF(日誌追加)。RDB也可理解為半持久化,也是redis預設的持久化方式。AOF的持久化更好,但是對效能有影響。實際生產中是兩種方式並用。
VM虛擬記憶體已經不再推薦,嚴重影響效能
1 :RDB 記憶體快照
RDB稱為記憶體快照,將記憶體中的資料快照按照我們設定的配置周期性的寫入硬碟。
原理:
1. redis調用fork,現在有了子進程和父進程。
2. 父進程繼續處理client請求,(不阻塞)子進程負責將記憶體內容寫入到臨時檔案。由於os的寫時複製機制(copy on write)父子進程會共用相同的物理頁面,當父進程處理寫請求時os會為父進程要修改的頁面棄置站台,而不是寫共用的頁面。所以子進程的地址空間內的資料是fork時刻整個資料庫的一個快照。(如果在整個子進程將資料寫入硬碟過程中,無任何寫請求,那麼父子進程共用 記憶體資料。一旦有寫操作,會copy一份副本。如果copy了一份副本,那麼將佔用雙倍的記憶體,這就是為什麼生產環境中力求資料量不超過記憶體一半的原因)
3. 當子進程將快照寫入臨時檔案完畢後,用臨時檔案替換原來的快照檔案,然後子進程退出(fork一個進程入內在也被複製了,即記憶體會是原來的兩倍)。
save和bgsave命令也會觸發RDB,進行持久化。save命令啟用主進程進行持久化,期間會阻塞用戶端請求,用得少。bgsave命令會啟用子進程進行持久化,和上面的原理一樣。
RDB持久化會丟失上次備份到奔潰這段時間內的資料,用來做冷備份還是不錯的。如果想獲得更好的持久性,AOF更合適。但是AOF得效能要差一些
2 :AOF 日誌追加 預設不開啟
AOF會把redis伺服器的每一次寫操作寫入appendonly.aof檔案中,這個檔案存在硬碟中。如果記憶體失效,redis伺服器會從這個檔案中讀取命令,進行恢複。作業系統本身的緩衝機制使得appendonly.aof的追加不會立即寫入硬碟,重啟時也會丟失部分修改寫操作。通過redis配置可以強制將緩衝立即寫入硬碟。
aof方式會使得.aof檔案越來越大。通過配置,可以週期性對.aof檔案進行重寫。命令bgrewriteaof,可以對aof檔案進行重寫。
下面是重寫.aof檔案的原理,而不是日誌追加的原理。日誌追加就是往.aof檔案末尾追加。
1. redis調用fork ,現在有父子兩個進程
2. 子進程根據fork時刻記憶體中的資料庫快照集,往臨時檔案中寫入重建資料庫狀態的命令(也遵守寫時複製)
3. 父進程繼續處理client請求,除了把寫命令寫入到原來的aof檔案中。同時把收到的寫命令緩衝起來。這樣就能保證如果子進程重寫失敗的話並不會出問題。
4. 當子進程把快照內容寫入已命令方式寫到臨時檔案中後,子進程發訊號通知父進程。然後父進程把緩衝的寫命令也寫入到臨時檔案。
5. 現在父進程可以使用臨時檔案替換老的aof檔案,並重新命名,後面收到的寫命令也開始往新的aof檔案中追加。
一般對redis做主從同步,主機不開啟任何持久化策略,保證最好的效能。而在從機上進行持久化,持久化採用兩種策略結合的方式
redis持久化機制