RDB(默認)
RDB是通過快照方式完成的,當滿足一定條件時,redis會自動將內存中的數據持久化到磁盤。
觸發快照的時機
- 符合自定義配置的快照規則。(在redis.conf中配置,下面會詳細介紹)
- 執行save或者bgsave命令
- 執行flushall命令
- 執行主從復制操作(第一次)
- 在快照進行的過程中,也就是生成文件的過程中,不會對原有的rdb文件進行修改,直到快照生成完畢,直接將老的替換成新的,保證rdb文件任何時刻都是完整的。
- 我們可以通過定時備份rdb文件來實現redis數據的備份,rdb是壓縮的二進制文件,占用空間小,有利于傳輸
###快照設置規則 save {多少秒內} {數據變化了多少}
例如:save 100 1:在100秒內,至少有一個鍵被修改就進行快照;save 200 4:在200秒內,至少4個鍵被修改就進行快照。
RDB的優缺點
- 缺點:使用RDB進行持久化,在redis突然異常退出的時候,會丟失最后一次快照之后的數據。但是,可以根據組合設置自動快照的方式,降低數據損失,確保在接受范圍內。如果數據較為重要,可以使用AOF方式
- 優點:使用RDB方式可以最大化redis性能,在快照過程中,我們可以看到主進程只需要fork出一個子進程即可,剩下的工作全部由子進程完成,父進程無需進行任何的磁盤I/O操作。但是,如果數據集較大,在fork子進程的時候比較耗時,會導致redis在一段時間內停止處理請求。
默認情況下,redis是沒有開啟AOF(Append only file)的。在開始AOF之后,redis每接收到一條更改redis數據的命令,就會將該命令寫入硬盤中的AOF文件。很明顯,該過程會降低redis的性能,但大部分情況下是能夠接受的,同時,使用性能較好的硬盤可以提高AOF性能
AOF配置方式
# 開啟appendonly參數appendonly true# 設置AOF文件位置dir ./# 設置AOF文件名稱,默認是appendonly.aofappendfilename appendonly.aof<br data-filtered="filtered">
RESP協議
Redis客戶端使用RESP協議與Redis服務端進行通信,該協議是專門為redis設計的,但是也可以用于其他C-S項目。
- 間隔符號:在linux中是rn,在windows中是n
- 簡單字符串以'+'開頭
- 錯誤Errors,以'-'開頭
- 整數類型Integer,以':'開頭
- 大字符串以'$'開頭
- 數組類型Arrays,以'*'開頭
redis通過將所有的寫入命令記錄到AOF文件中,來持久化數據。而將命令記錄到AOF文件的過程,可以分成三個階段:
- 命令傳播
- 緩存追加
- 文件寫入和保存
redis將執行完的命令,命令參數,命令參數格個數等內容發送到AOF程序。當redis客戶端執行命令的時候,通過連接,將協議文本發送到redis,redis接收到協議文本之后,根據內容,選擇適當的命令函數,將協議文本轉換成Redis字符串對象,在命令函數執行完成后,將命令參數發送到AOF程序。
緩存追加
AOF程序接收到命令參數之后,會將其從字符串對象轉換成協議內容,再將協議內容追加到AOF緩存中。AOF緩存是在redisServer結構的aof_buf中,新的內容會被追加到aof_buf末尾。aof_buf保持著所有未被寫入到AOF文件的協議文本。
文件寫入和保存
將AOF緩存內容寫入到AOF文件,并保持到磁盤。 當服務器的常規函數被執行,或者事件處理器被執行的時候,flushAppendOnlyFile函數將會被執行。會有以下兩個過程。
- WRITE:將AOF緩存中的內容寫入到AOF文件
- SAVE:調用fsync或者fdatasync函數,將AOF文件保存到磁盤中
AOF一共有三種保存模式
- AOF_FSYNC_NO:不保存。在這種模式下,每次調用flushAppendOnlyFile函數,write會被執行,而save會被忽略。而save只有在以下三種條件下會觸發,redis關閉,aof功能關閉,系統的寫緩存被刷新(可能是緩存滿了,或者定期執行保持操作)。這三種情況下執行save操作會引起redis主線程的阻塞。
- AOF_FSYNC_EVERYSEC(默認):每秒保存一次。save每秒被執行一次,但是save由后臺子線程完成,不會導致redis主線程阻塞。
- AOF_FSYNC_ALWAYS:每執行一個命令保存一次。這種情況下,每執行一個命令write和save都會被執行,而且save操作由主線程完成,會導致redis的阻塞。安全性較高,性能較差,因此不推薦使用。
Redis可以在AOF文件過大的時候,在后臺(子進程)對AOF文件進行重寫。重寫之后的新文件,包含恢復當前數據集所需的最小命令集合。重寫,并不會對AOF文件進行讀取和寫入,針對的是數據庫中的當前鍵。
優化前set s1 1set s1 2set s1 3優化后set s1 3<br data-filtered="filtered">
AOF文件優化原理
AOF的重寫是通過子進程實現的,因此,主線程是繼續工作的,有可能對新的數據進行修改,有可能會導致數據庫的數據和重寫之后的數據不一致。redis通過增加一個AOF重寫緩存來解決這個問題,當fork出子進程之后,新的命令不僅會追加到現有的AOF文件中,還會添加一份數據到這個緩存當中。
重寫過程分析(需要保證從寫的操作是絕對安全的)
Redis創建新的AOF文件之后,會繼續將命令添加到原有的AOF文件中,即使數據庫突然宕機了,原有的AOF文件和文件內容也不會有損失。而當新的AOF文件創建完畢之后,會直接把舊的替換掉,往新的AOF文件中添加命令。
當子進程在進行重寫時,主進程會完成下列工作
- 處理請求,將新的命令繼續添加到AOF文件中,同時將命令添加到AOF重寫緩存中。保證數據的一致行,避免出現數據丟失。
- 當子進程重寫完畢之后會向主進程發送一個完成信號,這時主進程會把重寫緩存中的內容添加到新的AOF文件中,這樣新的AOF文件,數據庫,舊的AOF文件的內容就完全一致了。然后對新的AOF文件改名,覆蓋原有的AOF文件。
這樣程序就完成了新舊AOF文件的替換工作。而當處理完成之后,主進程就會繼續接受請求。整個重寫過程中只有最后的緩存寫入和改名替換的操作會導致主進程阻塞,其他時候不會影響redis的正常工作,把AOF重寫對redis的性能影響降到最低。