client Redis[內存] --> 內存數據、磁盤數據----> 磁盤,Redis官方提供了兩種不同的持久化方案將內存中的數據存儲在硬盤中:
快照(Snapshot)
AOF只追加日志文件。
1、快照(Snapshot)
1、快照的特點:
快照的方式是將某一時刻的數據全部寫入到磁盤中,也是Redus中默認的開啟持久化的方式。保存的文件是以.rdb結尾的文件。
需要注意的是:redis在哪個目錄下啟動,哪一個就是redis的工作目錄,后面的rdb持久化或者AOF持久化,產生的文件都存在于redis的當前工作目錄下。在哪里啟動就會讀取哪里的快照文件
2、快照的生成的方式:
1、客戶端的方式:通過bigsave、save指令
1、bigsave指令
當主進程接收到客戶端的寫命令的請求,主進程會調用fork函數來創建一個子進程,子進程負責進行快照,并將快照寫入到磁盤中。此時的父類會繼續的接受客戶端的寫數據的請求。
2、save指令
當主進程接收到客戶端的寫數據的請求,主進程會調用fork函數來創建一個子進程來進行快照并將數據存入磁盤中,此時子進程會拒絕外界客戶端寫數據的請求一直到子進程結束。
fork :當一個進程創建子線程的時候,底層的操作系統會創建進程的一個副本,在類似于unix系統中創建子線程的操作會進行優化,在剛開始的時候,父子進程共享相同的內存,知道父類進程或者子類進程對內存進行了寫之后,對被寫入的內存的共享才會結束服務
2、配置器配置自動觸發
1、修改配置文件redis.conf文件,用戶在redis.conf配置文件中設置了save配置選項,redis會在save選項條件滿足之后自動的觸發一次bgsave命令,如果設置多個save配置選項,當任意一個save配置文件條件滿足,redis也會觸發一次bgsave命令
?3、服務器接收客戶端shutdown指令
當redis通過shutdown指令接收到關閉服務器的請求時,會執行一個save命令,阻塞所有的客戶端,不再執行客戶端執行發送的任何命令,并且在save命令執行完畢之后關閉服務器。
修改快照的位置和名稱: redis.conf 配置文件中:#1.修改生成快照名稱
- dbfilename dump.rdb# 2.修改生成位置
- dir ./
2、AOF只追加日志文件
1、特點:
將客戶端的所有的寫的命令都記錄在日志文件中,AOF持久化會將被執行的寫命令寫到AOF的文件中。以此來記錄數據發生的變化。因此只要Redis從頭執行一下這個日志文件就可以恢復到原先的數據集。
2、開啟AOF:
在redis中是默認不開啟AOF持久化的,需要在配置文件中開啟:
1、開啟AOF持久化:修改 appendonly yes
修改 appendfilename "appendonly.aof" 指定生成文件名稱
3、日志追加的頻率:
# 1.always 【謹慎使用】
- 說明: 每個redis寫命令都要同步寫入硬盤,嚴重降低redis速度
- 解釋: 如果用戶使用了always選項,那么每個redis寫命令都會被寫入硬盤,從而將發生系統崩潰時出現的數據丟失減到最少;遺憾的是,因為這種同步策略需要對硬盤進行大量的寫入操作,所以redis處理命令的速度會受到硬盤性能的限制;
- 注意: 轉盤式硬盤在這種頻率下200左右個命令/s ; 固態硬盤(SSD) 幾百萬個命令/s;
- 警告: 使用SSD用戶請謹慎使用always選項,這種模式不斷寫入少量數據的做法有可能會引發嚴重的`寫入放大`問題,導致將固態硬盤的壽命從原來的幾年降低為幾個月。# 2.everysec 【推薦默認】
- 說明: 每秒執行一次同步顯式的將多個寫命令同步到磁盤
- 解釋: 為了兼顧數據安全和寫入性能,用戶可以考慮使用everysec選項,讓redis每秒一次的頻率對AOF文件進行同步;redis每秒同步一次AOF文件時性能和不使用任何持久化特性時的性能相差無幾,而通過每秒同步一次AOF文件,redis可以保證,即使系統崩潰,用戶最多丟失一秒之內產生的數據。 # 3.no 【不推薦】
- 說明: 由操作系統決定何時同步
- 解釋:最后使用no選項,將完全由操作系統決定什么時候同步AOF日志文件,這個選項不會對redis性能帶來影響但是系統崩潰時,會丟失不定數量的數據,甚至丟失全部數據,另外如果用戶硬盤處理寫入操作不夠快的話,當緩沖區被等待寫入硬盤數據填滿時,redis會處于阻塞狀態,并導致redis的處理命令請求的速度變慢。
4、修改同步的頻率:
# 1.修改日志同步頻率
- 修改appendfsync everysec|always|no 指定
3、AOF重寫:
1、AOF帶來的問題:
AOF會將所有寫數據的命令都寫入到日志文件中,假設連續的一百次操作都是相同,此時AOF會記錄這一百次的記錄,就會導致文件過大,因為要恢復數據庫的狀態其實文件中保存一條數據就夠了,為了壓縮aof的持久化文件Redis提供了AOF重寫(ReWriter)機制。
2、AOF重寫:
在一定的程度上可以減少AOF文件的體積,并且能夠保證數據不丟失。
3、AOF觸發的方式:
1、客戶端觸發的方式:
bgrewriteaof
2、服務器配置方式自動的觸發:
- 配置redis.conf中的auto-aof-rewrite-percentage選項
- 如果設置auto-aof-rewrite-percentage值為100和auto-aof-rewrite-min-size 64mb,
并且啟用的AOF持久化時,那么當AOF文件體積大于64M,并且AOF文件的體積比上一次重寫之后體積大了至少一倍(100%)時,會自動觸發,
如果重寫過于頻繁,用戶可以考慮將auto-aof-rewrite-percentage設置為更大
4、AOF的重寫機制的原理
1、7.0.0版本之前:
1、首先,當主進程觸發AOF重寫機制的時候,主進程會調用fork函數創建一個子進程進行快照,并將生成的dump文件用指令的方式寫入臨時文件中,子進程會將完成寫入臨時文件通知給主進程。
2、此時主進程還會繼續接受客戶端的寫數據的命令,主進程會繼續向原先的aof文件中記錄命令,同時也會將命令緩存到內存中,當主進程接受到子進程寫入完成這個命令的時候,會將緩存在內存中的寫數據指令同步到臨時文件中。
3、當內存中的指令寫入后,臨時文件就會替換掉原先的aof文件。
2、7.0.0版本之后:
1、首先,當主進程觸發AOF重寫機制的時候,主進程會調用fork函數創建一個子進程進行快照,并將生成的dump文件用指令的方式寫入臨時文件中,和原先快照文件一起以命令的方式寫入到臨時文件中。
2、此時主進程還會繼續接收客戶端的寫數據的命令,此時將命令寫入新的增量文件中,同時也會將命令寫入到就的增量文件中(aof文件)。
3、然后將舊的增量文件和臨時文件合并生成一個臨時清單
4、底層通過讀取這個臨時清單去重寫生成一個新的rdb文件去替換原先舊的基本文件。
與之前的最大的改變就是將原先的單個AOF文件拆分成一個基本文件和多個增來文件,基本文件負責的是重寫AOF之前已經存在的數據和一些快照的數據。增量文件負責的是一些增量的修改。都會存在在一個單獨的文件中,并由清單文件所管理。
5、總結:
兩種持久化方案既可以同時使用(aof),又可以單獨使用,在某種情況下也可以都不使用,具體使用那種持久化方案取決于用戶的數據和應用決定。
無論使用AOF還是快照機制持久化,將數據持久化到硬盤都是有必要的,除了持久化外,用戶還應該對持久化的文件進行備份(最好備份在多個不同地方)。