1. 程式人生 > 實用技巧 >網路知識 | 《圖解TCP/IP》讀書筆記(下)

網路知識 | 《圖解TCP/IP》讀書筆記(下)

RDB快照(snapshot)

在預設情況下, Redis 將記憶體資料庫快照儲存在名字為 dump.rdb 的二進位制檔案中。

你可以對 Redis 進行設定, 讓它在“ N 秒內資料集至少有 M 個改動”這一條件被滿足時, 自動儲存一次資料集。

比如說, 以下設定會讓 Redis 在滿足“ 60 秒內有至少有 1000 個鍵被改動”這一條件時, 自動儲存一次資料集:

# save 60 1000

關閉RDB只需要將所有的save儲存策略註釋掉即可

還可以手動執行命令生成RDB快照,進入redis客戶端執行命令savebgsave可以生成dump.rdb檔案,每次命令執行都會將所有redis記憶體快照到一個新的rdb檔案裡,並覆蓋原有rdb快照檔案。

save是同步命令,bgsave是非同步命令,bgsave會從redis主程序fork(fork()是linux函式)出一個子程序專門用來生成rdb快照檔案

save與bgsave對比:

命令savebgsave
IO型別同步非同步
是否阻塞redis其它命令否(在生成子程序執行呼叫fork函式時會有短暫阻塞)
複雜度O(n)O(n)
優點不會消耗額外記憶體不阻塞客戶端命令
缺點阻塞客戶端命令需要fork子程序,消耗記憶體
RDB檔案存放位置:

在這裡插入圖片描述
在這裡插入圖片描述

檢視存放的檔案:
在這裡插入圖片描述

是否開啟壓縮模式:

在這裡插入圖片描述

RDB常用配置總結

下面是RDB常用的配置項,以及預設值(前面介紹過的這裡不再詳細介紹):

  • save m n:bgsave自動觸發的條件;如果沒有save m n配置,相當於自動的RDB持久化關閉,不過此時仍可以通過其他方式觸發。
  • stop-writes-on-bgsave-error yes:當bgsave出現錯誤時,Redis是否停止執行寫命令;設定為yes,則當硬碟出現問題時,可以及時發現,避免資料的大量丟失;設定為no,則Redis無視bgsave的錯誤繼續執行寫命令,當對Redis伺服器的系統(尤其是硬碟)使用了監控時,該選項考慮設定為no。
  • rdbcompression yes:是否開啟RDB檔案壓縮。
  • rdbchecksum yes:是否開啟RDB檔案的校驗,在寫入檔案和讀取檔案時都起作用;關閉checksum在寫入檔案和啟動檔案時大約能帶來10%的效能提升,但是資料損壞時無法發現。
  • dbfilename dump.rdb:RDB檔名。
  • dir ./:RDB檔案和AOF檔案所在目錄。

配置自動生成rdb檔案後臺使用的是bgsave方式。

AOF(append-only file)

快照功能並不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那麼伺服器將丟失最近寫入、且仍未儲存到快照中的那些資料。從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化,將修改的每一條指令記錄進檔案appendonly.aof中

你可以通過修改配置檔案來開啟 AOF 功能:

# appendonly yes

從現在開始, 每當 Redis 執行一個改變資料集的命令時(比如 SET), 這個命令就會被追加到 AOF 檔案的末尾。

這樣的話, 當 Redis 重新啟動時, 程式就可以通過重新執行 AOF 檔案中的命令來達到重建資料集的目的。

你可以配置 Redis 多久才將資料 fsync 到磁碟一次。

有三個選項:

  • appendfsync always:每次有新命令追加到 AOF 檔案時就執行一次 fsync ,非常慢,也非常安全。
  • appendfsync everysec:每秒 fsync 一次,足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料。
  • appendfsync no:從不 fsync ,將資料交給作業系統來處理。更快,也更不安全的選擇。

推薦(並且也是預設)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。

AOF重寫

AOF檔案裡可能有太多沒用指令,所以AOF會定期根據記憶體的最新資料生成aof檔案

例如,執行了如下幾條命令:

127.0.0.1:6379> incr readcount (integer) 1 127.0.0.1:6379> incr readcount (integer) 2 127.0.0.1:6379> incr readcount (integer) 3 127.0.0.1:6379> incr readcount (integer) 4 127.0.0.1:6379> incr readcount (integer) 5

重寫後AOF檔案裡變成

*3 $3 SET $2 readcount $1 5

如下兩個配置可以控制AOF自動重寫頻率

# auto-aof-rewrite-min-size 64mb //aof檔案至少要達到64M才會自動重寫,檔案太小恢復速度本來就很快,重寫的意義不大

# auto-aof-rewrite-percentage 100 //aof檔案自上一次重寫後文件大小增長了100%則再次觸發重寫

當然AOF還可以手動重寫,進入redis客戶端執行命令bgrewriteaof重寫AOF

注意,AOF重寫redis會fork出一個子程序去做,不會對redis正常命令處理有太多影響

RDB 和 AOF ,我應該用哪一個?

命令RDBAOF
啟動優先順序
體積
恢復速度
資料安全性容易丟資料根據策略決定

redis啟動時如果既有rdb檔案又有aof檔案則優先選擇aof檔案恢復資料,因為aof一般來說資料更全一點。

檔案重寫的觸發

檔案重寫的觸發,分為手動觸發和自動觸發:

  • 手動觸發:直接呼叫bgrewriteaof命令,該命令的執行與bgsave有些類似:都是fork子程序進行具體的工作,且都只有在fork時阻塞。

img

此時伺服器執行日誌如下:

img

  • 自動觸發:根據auto-aof-rewrite-min-size和auto-aof-rewrite-percentage引數,以及aof_current_size和aof_base_size狀態確定觸發時機。
  • auto-aof-rewrite-min-size:執行AOF重寫時,檔案的最小體積,預設值為64MB。
  • auto-aof-rewrite-percentage:執行AOF重寫時,當前AOF大小(即aof_current_size)和上一次重寫時AOF大小(aof_base_size)的比值。

其中,引數可以通過config get命令檢視:

img

狀態可以通過info persistence檢視:

img

只有當auto-aof-rewrite-min-size和auto-aof-rewrite-percentage兩個引數同時滿足時,才會自動觸發AOF重寫,即bgrewriteaof操作。

自動觸發bgrewriteaof時,可以看到伺服器日誌如下:

img

檔案重寫的流程

檔案重寫流程如下圖所示:

圖片來源:http://www.cnblogs.com/yangmingxianshen/p/8373205.html

img

關於檔案重寫的流程,有兩點需要特別注意:

  • 重寫由父程序fork子程序進行;
  • 重寫期間Redis執行的寫命令,需要追加到新的AOF檔案中,為此Redis引入了aof_rewrite_buf快取。

對照上圖,檔案重寫的流程如下:

  • Redis父程序首先判斷當前是否存在正在執行 bgsave/bgrewriteaof的子程序,如果存在則bgrewriteaof命令直接返回,如果存在bgsave命令則等bgsave執行完成後再執行。前面曾介紹過,這個主要是基於效能方面的考慮。

  • 父程序執行fork操作建立子程序,這個過程中父程序是阻塞的。

  • 父程序fork後,bgrewriteaof命令返回”Background append only file rewrite started”資訊並不再阻塞父程序,並可以響應其他命令。Redis的所有寫命令依然寫入AOF緩衝區,並根據appendfsync策略同步到硬碟,保證原有AOF機制的正確。

    由於fork操作使用寫時複製技術,子程序只能共享fork操作時的記憶體資料。由於父程序依然在響應命令,因此Redis使用AOF重寫緩衝區(圖中的aof_rewrite_buf)儲存這部分資料,防止新AOF檔案生成期間丟失這部分資料。也就是說,bgrewriteaof執行期間,Redis的寫命令同時追加到aof_buf和aof_rewirte_buf兩個緩衝區。

  • 子程序根據記憶體快照,按照命令合併規則寫入到新的AOF檔案。

  • 子程序寫完新的AOF檔案後,向父程序發訊號,父程序更新統計資訊,具體可以通過info persistence檢視。

    父程序把AOF重寫緩衝區的資料寫入到新的AOF檔案,這樣就保證了新AOF檔案所儲存的資料庫狀態和伺服器當前狀態一致。

    使用新的AOF檔案替換老檔案,完成AOF重寫。

檔案校驗

與載入RDB檔案類似,Redis載入AOF檔案時,會對AOF檔案進行校驗,如果檔案損壞,則日誌中會列印錯誤,Redis啟動失敗。但如果是AOF檔案結尾不完整(機器突然宕機等容易導致檔案尾部不完整),且aof-load-truncated引數開啟,則日誌中會輸出警告,Redis忽略掉AOF檔案的尾部,啟動成功。aof-load-truncated引數預設是開啟的:

img

AOF常用配置總結

下面是AOF常用的配置項,以及預設值;前面介紹過的這裡不再詳細介紹。

  • appendonly no:是否開啟AOF
  • appendfilename “appendonly.aof”:AOF檔名
  • dir ./:RDB檔案和AOF檔案所在目錄
  • appendfsync everysec:fsync持久化策略
  • no-appendfsync-on-rewrite no:AOF重寫期間是否禁止fsync;如果開啟該選項,可以減輕檔案重寫時CPU和硬碟的負載(尤其是硬碟),但是可能會丟失AOF重寫期間的資料;需要在負載和安全性之間進行平衡
  • auto-aof-rewrite-percentage 100:檔案重寫觸發條件之一
  • auto-aof-rewrite-min-size 64mb:檔案重寫觸發提交之一
  • aof-load-truncated yes:如果AOF檔案結尾損壞,Redis啟動時是否仍載入AOF檔案

1)info Persistence

執行結果如下:

img

Redis 4.0 混合持久化

重啟 Redis 時,我們很少使用 RDB來恢復記憶體狀態,因為會丟失大量資料。我們通常使用 AOF 日誌重放,但是重放 AOF 日誌效能相對 RDB來說要慢很多,這樣在 Redis 例項很大的情況下,啟動需要花費很長的時間。 Redis 4.0 為了解決這個問題,帶來了一個新的持久化選項——混合持久化。

通過如下配置可以開啟混合持久化:

# aof-use-rdb-preamble yes

如果開啟了混合持久化,AOF在重寫時,不再是單純將記憶體資料轉換為RESP命令寫入AOF檔案,而是將重寫這一刻之前的記憶體做RDB快照處理,並且將RDB快照內容和增量的AOF修改記憶體資料的命令存在一起,都寫入新的AOF檔案,新的檔案一開始不叫appendonly.aof,等到重寫完新的AOF檔案才會進行改名,原子的覆蓋原有的AOF檔案,完成新舊兩個AOF檔案的替換。

於是在 Redis 重啟的時候,可以先載入 RDB 的內容,然後再重放增量 AOF 日誌就可以完全替代之前的 AOF 全量檔案重放,因此重啟效率大幅得到提升。

混合持久化AOF檔案結構

在這裡插入圖片描述