環境
Centos 7.4 ; docker-ce.19.03.8; kernel-5.6.5; redis-4.0
持久化模式
- 快照模式
RDB持久化是通過創建快照來獲得數據副本,即簡單粗暴的直接保存鍵值對數據內容
要啟用RDB(並關閉AOF),我們需要修改Redis的配置文件
redis.conf:
requirepass password
save 60 1000
stop-writes-on-bgsave-error no
rdbcompression no
dbfilename dump.rdb
appendonly no #是否啟用AOF
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
dir /data/
- aof日志模式
修改redis配置文件,使AOF生效,並關閉RDB
啟動redis服務,並觀察redis_data目錄下是否有dump.rdb文件生成,有生成,則證明備份成功
數據恢復,只要確保該dump.rdb存在,redis便會自動去讀取其中的數據
AOF持久化會將被執行的寫命令寫到AOF文件的末尾,以此來記錄數據發生的變化。
因此,Redis 只要從頭到尾重新執行一次AOF 文件包含的所有寫命令,就可以恢復AOF文件所記錄的數據集。
redis.conf:
requirepass password
save 60 1000
stop-writes-on-bgsave-error no
rdbcompression no
dbfilename dump.rdb
appendonly yes #是否啟用AOF
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
dir /data/
配置文件說明
- RDB配置說明
* save: 多久執行一次自動快照操作
比如設置為 ```save 60 1000``` ,那么就表示在60秒之內,如果有1000次寫入的話,Redis就會自動觸發BGSAVE命令
* stop-writes-on-bgsave-error: 在創建快照失敗后是否仍然繼續執行寫命令
* rdbcompression: 是否對快照文件進行壓縮
* yes: 開啟,這種情況下,Redis會采用LZF算法對rdb文件進行壓縮
* no: 關閉
* dbfilename: 快照文件名
* dir: 快照文件存放目錄
### RDB觸發條件
RDB的觸發條件會比AOF麻煩,大致可以分為以下幾種:
* 通過redis-cli等客戶端直接發送指令: ```BGSAVE```
BGSAVE指令,會讓Redis調用fork創建一個子進程在后台運行,子進程將會負責創建快照到磁盤中
在演示案例中,啟動redis的docker容器后,在redis-cli中輸入 ```BGSAVE``` 后,能夠在./redis_data目錄下生成一個temp-17.rdb文件(或者其他以rdb結尾的)
* 通過redis-cli等客戶端直接發送指令:```SAVE```
SAVE指令**(注意跟配置中的save沒有半毛錢關系)**,會讓Redis主進程直接開始創建快照,但在創建快照的過程中,Redis不會響應其他命令請求
在演示案例中,啟動redis的docker容器后,在redis-cli中輸入 ```SAVE``` 后,能夠在./redis_data目錄下生成一個temp-17.rdb文件(或者其他以rdb結尾的)
* 通過配置項```save```進行觸發
具體請參照上文的參數說明
* 通過SHUTDOWN命令關閉Redis服務器時,Redis會自動觸發一個SAVE指令
* 通過標准TERM信號kill掉Redis服務時,Redis也會自動觸發一個SAVE指令
* 通過Redis主從服務器的復制請求
主服務器收到從服務器的復制請求時,會觸發一次BGSAVE指令(當且僅當主服務器沒有子進程在執行BGSAVE)
* 通過docker-compose啟動Redis容器
我將Docker容器中的redis服務所產生的備份文件,映射在宿主機的./redis_data目錄下
* 修改redis配置文件,使AOF生效,並關閉RDB
這里將上面的redis.conf內容復制替換到./redis_config/redis.conf文件中即可
* 啟動redis服務,並觀察redis_data目錄下是否有dump.rdb文件生成,有生成,則證明備份成功
* 數據恢復的話,我們不需要做其他操作,只要確保該dump.rdb存在,redis便會自動去讀取其中的數據
上述配置會通過docker-compose的配置,映射到Redis容器中並啟用
- AOF配置說明
上述配置中與AOF相關的配置如下
* appendonly: 是否啟用AOF
* yes: 啟用AOF
* no: 關閉AOF
* appendfsync: 啟用AOF后的數據同步頻率
* alaways: 每個Redis寫命令都要同步寫入硬盤。這樣做會嚴重降低Redis 的速度 (不建議)
* everysec: 每秒執行一次同步,顯式地將多個寫命令同步到硬盤 (推薦,對性能沒有太大影響)
* no: 讓操作系統來決定應該何時進行同步。(不建議)
Redis將不對AOF文件執行任何顯式的同步操作,如果用戶的硬盤處理寫入操作的速度不夠快的話,那么當緩沖區被等待寫入硬盤的數據填滿時,Redis的寫入操作將被阻塞,並導致Redis處理命令請求的速度變慢
* no-appendfsync-on-rewrite:在對AOF進行壓縮(也被稱為重寫機制)的時候能否執行同步操作
* yes: 不允許
* no: 允許
* auto-aof-rewrite-percentage:多久執行一次AOF壓縮,單位是百分比
* auto-aof-rewrite-min-size:需要壓縮的文件達到多少時開始執行
auto-aof-rewrite-percentage跟auto-aof-rewrite-min-size需要配套使用,比如當我們設置auto-aof-rewrite-percentage為100,設置auto-aof-rewrite-min-size為64mb時
redis會在AOF產生的文件比64M大時,並且AOF文件的體積比上一次重寫之后至少增大了一倍(100%)才執行BGREWRITEAOF重寫命令
如果覺得AOF重寫執行得過於頻繁,我們可以把auto-aof-rewrite-percentage設置100以上,比如200,就可以降低重寫頻率
這里可以參考Redis的官方手冊,寫的非常清楚:[https://redislabs.com/ebook/part-2-core-concepts/chapter-4-keeping-data-safe-and-ensuring-performance/4-1-persistence-options/4-1-3-rewritingcompacting-append-only-files/](https://redislabs.com/ebook/part-2-core-concepts/chapter-4-keeping-data-safe-and-ensuring-performance/4-1-persistence-options/4-1-3-rewritingcompacting-append-only-files/)
* dir:備份文件存放目錄
### AOF觸發條件
直接根據appendfsync的設置進行觸發
### AOF重寫機制
在上面的配置中,已經通過auto-aof-rewrite-percentage和auto-aof-rewrite-min-size兩個參數,簡單介紹了Redis的BGREWRITEAOF重寫命令
那么,為什么要用AOF重寫機制呢?
因為AOF持久化是通過保存被執行的寫命令來記錄Redis數據庫狀態的,所以AOF文件隨着時系統運行會越來越大
而過於龐大的AOF文件會產生以下不良影響
* 影響Redis服務性能;
* 占用服務器磁盤空間;
* AOF還原數據狀態的時間增加;
所以Redis提供了一套AOF重寫機制,通過創建一個新的AOF文件來替換掉舊的AOF文件,這兩個文件所保存的數據狀態是相同的,但新的AOF文件不會包含冗余命令,所以體積會較舊AOF文件小很多
但在實際的使用中,我們需要非常小心,不能讓Redis的重寫命令執行的過於頻繁 **(注意:auto-aof-rewrite-percentage的單位是百分比,值越大,重寫頻率越低,也千萬別出現0這種值)** 因為BGREWRITEAOF的工作原理和BGSAVE創建快照的工作原理非常相似:Redis會創建一個子進程,然后由子進程負責對AOF文件進行重寫,因為AOF文件重寫也需要用到子進程,所以快照持久化因為創建子進程而導致的性能問題和內存占用問題,在AOF持久化中也同樣存在
更具體的AOF重寫工作原理:
* Fork主進程,產生一個帶有數據副本的子進程在后台執行
Redis這樣設計可以確保在重寫過程中,不影響Redis主進程的服務正常運行,同時通過處理數據副本來保證數據的安全性**(注意,重寫是針對數據副本來進行處理,而不是針對舊的AOF文件)**
* 子進程Fork完成后,Redis將啟用AOF重寫緩沖區,此刻開始,新的寫入命令會被寫入AOF緩沖區和AOF重寫緩沖區中
這里啟用的AOF重寫緩沖區可以確保:在執行AOF重寫的過程中,任何新的寫入命令產生,都不會導致新AOF文件的數據狀態與Redis數據庫狀態不一致
* 子進程完成對AOF文件的重寫后,通知父進程
* 父進程收到通知后,將AOF重寫緩沖區的內容全部寫入新的AOF文件中
* 父進程將新的AOF文件替換掉舊的AOF文件**(注意,這一步會造成Redis阻塞,但問題不大)**