標籤:
一、Redis持久化
Redis是一個支援持久化的記憶體資料庫,redis需要經常將記憶體中的資料同步到磁碟來保證持久化。
redis提供了不同層級的持久化方法:
- Snapshotting(快照,預設):能夠在指定的時間間隔對你的操作進程快照儲存
- Append-only file(縮寫aof):記錄每次對伺服器寫的操作,當伺服器重啟時會重新執行這些命令來恢複原始的資料
- 如果你只希望你的資料在伺服器啟動並執行時候存在,你也可以不使用任何持久化方式
- 你也可以同時開啟兩種持久化方法,這種情況下,當redis重啟的時候會優先載入aof原件來恢複未經處理資料,因為通常情況下,aof檔案儲存的資料集要比rdb檔案儲存的資料集要完整
二、快照方式(snapshotting)
預設情況下,Redis將資料庫快照集儲存在一個dump.rdb的二進位檔案中。
1、配置方式
可以通過配置設定自動做快照持久化的方式。我們可以配置redis在n秒內如果超過m個key被修改就自動做快照,下面是預設的快照儲存配置:
save 900 1 //900秒內如果超過1個key被修改,則發起快照儲存save 300 10 //300秒內容如超過10個key被修改,則發起快照儲存save 60 10000
2、工作原理
當Redis需要儲存dump.rdb檔案時,伺服器執行以下操作:
Redis調用forks,同時擁有父進程和子進程
子進程將資料集寫入到一個臨時rdb檔案中
當子進程完成對新rdb檔案的寫入時,redis用新rdb檔案替換原來的rdb檔案,並刪除舊的rdb檔案
client也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主線程中儲存快照的,由於redis是一個主線程來處理所有client的請求,這種方式會阻塞所有client請求。
三、只追加操作的檔案(Append-only file AOF)
快照功能並不是非常耐久,如果redis因為某些原因而造成故障停機那麼伺服器將丟失最近寫入、且仍未儲存到快照的那些資料。從1.1版本開始,redis增加了一種完全耐久的持久化方式:AOF持久化。
1、配置方式
aof比快照方式有更好的持久化性。在使用aof方式時,redis會將每一個收到的寫命令都通過write函數追加到檔案(預設是appendonly.aof)中。當redis重啟時會通過重新執行檔案中的儲存的寫命令來在記憶體中重建整個資料庫的內容。
由於作業系統會在核心中緩衝write做的修改,所以可能不是立即寫到磁碟上,這樣aof方式的持久化也還是有可能會丟失部分修改。我們可以通過設定檔告訴redis我們想要通過fsync函數強制作業系統寫入到磁碟的時機,有三種方式如下(預設:每秒fsync一次):
appendonly yes #啟用aof持久化方式# appendfsync always #每次收到寫命令就立即強制寫入磁碟,最慢的,但是保證完全的持久化,不推薦使用appendfsync everysec #每秒鐘強制寫入磁碟一次,在效能和持久化方面做了很好的折中,推薦# appendfsync no #完全依賴os,效能最好,持久化沒保證
選項分析:
1、appendfsync no
當設定appendfsync為no時,Redis不會主動調用fsync去將aof日誌同步到磁碟,完全依賴於作業系統
2、appendfsync everysec
當設定為appendfsync為everysec的時候,Redis會預設每隔一秒進行一次fsync調用,將緩衝區中的資料寫到磁碟。
3、appendfsync always
當設定appendfsync為always時,每一次寫操作都會調用一次fsync,這時資料是最安全的,當然,由於每次都會執行fsync,所以其效能也會受到影響。
在設定檔redis.windows.conf中設定appendonly yes 後,開啟redis伺服器,立即會產生一個append-only.aof空檔案。然後在用戶端中,輸入下面的命令
再查看append-only.aof檔案,內容為:
2、日誌重寫
因為aof的運作方式是不斷的將命令追加到檔案的結尾,所以隨著寫入命令的不斷增加,aof檔案的體積也會變得越來越大。redis支援一種特性:可以在不打斷用戶端的情況下,對aof檔案進行重建(rebuild),執行bgrewriteaof命令,redis將產生一個新的aof檔案,這個檔案將包含重建當前資料集所需的最少命令。
3、工作原理
AOF重寫和rdb建立快照一樣,都是巧妙的利用了寫時複製機制:
- redis調用fork ,現在有父子兩個進程
- 子進程根據記憶體中的資料庫快照集,往臨時檔案中寫入重建資料庫狀態的命令
- 父進程繼續處理client請求,除了把寫命令寫入到原來的aof檔案中。同時把收到的寫命令緩衝起來。這樣就能保證如果子進程重寫失敗的話並不會出問題。
- 當子進程把快照內容寫入已命令方式寫到臨時檔案中後,子進程發訊號通知父進程。然後父進程把緩衝的寫命令也寫入到臨時檔案。
- 現在父進程可以使用臨時檔案替換老的aof檔案,並重新命名,後面收到的寫命令也開始往新的aof檔案中追加。
4、寫資料流程
- 用戶端向服務端發送寫請求(資料在用戶端的記憶體中)
- 資料庫服務端接收到寫請求的資料(資料在服務端的記憶體中)
- 服務端調用write這個系統調用,將資料往磁碟上寫(資料在系統記憶體的緩衝區中)
- 作業系統將緩衝區中的資料轉移到磁碟控制卡上(資料在磁碟緩衝區中)
- 磁碟控制卡將資料寫到磁碟的物理介質中(資料真正落到磁碟上)
四、備份Redis資料庫
我們可以在伺服器啟動並執行時候對rdb檔案進行複製:rdb檔案一旦被建立,就不會進行任何修改,當伺服器要建立一個新的rdb檔案時,它會先將檔案的內容儲存在一個臨時檔案裡面,當臨時檔案寫入完畢時,程式才使臨時檔案替換原來的rdb檔案。
- 建立一個定期任務(cron job), 每小時將一個 RDB 檔案備份到一個檔案夾, 並且每天將一個 RDB 檔案備份到另一個檔案夾。
- 確保快照的備份都帶有相應的日期和時間資訊, 每次執行定期任務指令碼時, 使用 find 命令來刪除到期的快照: 比如說, 你可以保留最近 48 小時內的每小時快照, 還可以保留最近一兩個月的每日快照。
- 至少每天一次, 將 RDB 備份到你的資料中心之外, 或者至少是備份到你運行 Redis 伺服器的物理機器之外。
五、參考資料
1、http://www.redis.cn/topics/persistence.html
Redis學習筆記三