一、Redis兩種持久化方式
對Redis而言,其數據是保存在內存中的,一旦機器宕機,內存中的數據會丟失,因此需要將數據異步持久化到硬盤中保存。這樣,即使機器宕機,數據能從硬盤中恢復。
常見的數據持久化方式:
1.快照:類似拍照記錄時光,快照是某時某刻將數據庫的數據做拍照記錄下其數據信息。如MYSQL的Dump,Redis的RDB模式
2.寫日志方式:是將數據的操作全部寫到日志當中,需要恢復的時候,按照日志記錄的操作記錄重新再執行一遍。例如MYSQL的Binlog,Redis的AAOF模式、
二、RDB
說明:
redis默認開啟,將redis在內存中保存的數據,以快照的方式持久化到硬盤中保存。
觸發機制:
1.save命令:阻塞方式,需要等redis執行完save后,才能執行其他get、set等操作。同步方式
2.bgsave命令:非阻塞,其原理是調用linux 的 fork()函數,創建redis的子進程,子進程進行創建 rdb 文件的操作。異步方式,
3.自動方式:在redis.conf文件中配置,如下 save <指定時間間隔> <執行指定次數更新操作> ,save 60 10000 表示 60秒年內有10000次操作會自動生成rdb文件。
# Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # # Note: you can disable saving at all commenting all the "save" lines. # # It is also possible to remove all the previously configured save # points by adding a save directive with a single empty string argument # like in the following example: # # save "" save 900 1 save 300 10 save 60 10000
4.其他方式
- 4.1 執行flushall命令,清空數據,幾乎不用
- 4.2 執行shutdown命令,安全關閉redis不丟失數據,幾乎用不到。
- 4.3 主從復制,在主從復制的時候,rdb文件作為媒介來關聯主節點和從節點的數據一致。
最佳配置參考:
vim redis.conf
# 1. 將自動生成rdb文件注釋掉 # save 900 1 # save 300 10 # save 60 10000 # The filename where to dump the DB # 2. rdb的文件名,改為dump+ 端口.rbd dbfilename dump-${port}.rdb # Note that you must specify a directory here, not a file name. # 3. 文件持久化目錄,日志目錄,改到分布式存儲中或者放到較大的硬盤目錄中。 dir /yourbigdata/ # 4. 在bgsave發生錯誤時停止寫入 stop-writes-on-bgsave-error yes # 5.采用壓縮方式,不然生成的rdb文件可能巨大無比。壓縮后主從復制拷貝文件小,速度也快。 rdbcompression yes # 6.采用校驗和 rdbchecksum yes
RDB優缺點
優點:
1 適合大規模的數據恢復。
2 如果業務對數據完整性和一致性要求不高,RDB是很好的選擇。
缺點:
1 不可控,容易丟失數據:數據的完整性和一致性不高,因為RDB可能在最后一次備份時宕機了。
2 耗時耗性能:備份時占用內存,因為Redis 在備份時會獨立創建一個子進程,將數據寫入到一個臨時文件(此時內存中的數據是原來的兩倍哦),最后再將臨時文件替換之前的備份文件。
所以Redis 的持久化和數據的恢復要選擇在夜深人靜的時候執行是比較合理的。
三、AOF
說明:
redis默認不開啟,采用日志的形式來記錄每個寫操作,並追加到 .aof 文件中。Redis 重啟的會根據日志文件的內容將寫指令從前到后執行一次以完成數據的恢復工作
生成AOF的三種策略:
1. always : 每條命令都會刷新到緩沖區,把緩沖區fsync到硬盤,對硬盤IO壓力大,一般sata盤只有幾百TPS,如果redis的寫入量非常大,那對硬盤的壓力也橫刀。
2. everysec: 每秒把緩沖區fsync 到硬盤,如果出現故障,會丟失1s(默認配置是1秒)的數據。一般使用這種。
3. no : 由操作系統來定什么時候fsync到硬盤中。 缺點:不可控
AOF重寫:
把過期的,沒有用的,重復的,可優化的命令簡化為很小的aof文件。實際上是redis內存中的數據回溯成aof文件。
如下圖所示:
作用:
1.減少硬盤占用量
2.加快恢復速度
AOF重寫的實現方式
1.bgrewriteaof 命令 : 從redis的主進程fork一個子進程生成包含當前redis內存數據的最小命令集、
2.AOF重寫配置:
# 1. aof文件增長率 auto-aof-rewrite-percentage 100 # 2. aof文件重寫需要的尺寸 auto-aof-rewrite-min-size 64mb
自動觸發時機:(需要同時滿足)
- 當前的aof文件大小 > aof文件重寫需要的尺寸
- (aof當前文件大小 - 上次aof的文件大小)/ 上次aof文件大小 > aof文件增長率
最佳配置參考:
vim redis.conf
# 1. 打開aof功能 appendonly yes # 2. 重命名aof文件名,以端口號區分 appendfilename "appendonly-${port}.aof" # 3. 使用everysec策略 appendfsync everysec
# 4. 文件持久化目錄,日志目錄,改到分布式存儲中或者放到較大的硬盤目錄中。
dir /yourbigdata/
# 5. 在aof重寫的時候,不做aof的append(追加)操作,這里出於性能考慮
no-appendfsync-on-rewrite yes
AOF優缺點
優點:
1.數據的完整性和一致性更高
缺點:
1.因為AOF記錄的內容多,文件會越來越大,數據恢復也會越來越慢。
2. AOF每秒fsync一次指令硬盤,如果硬盤IO慢,會阻塞父進程;風險是會丟失1秒多的數據;在Rewrite過程中,主進程把指令存到mem-buffer中,最后寫盤時會阻塞主進程。
四、關於Redis持久化方式RDB和AOF的缺點
原因是redis持久化方式的痛點,缺點比較明顯。
1、RDB需要定時持久化,風險是可能會丟兩次持久之間的數據,量可能很大。
2、AOF每秒fsync一次指令硬盤,如果硬盤IO慢,會阻塞父進程;風險是會丟失1秒多的數據;在Rewrite過程中,主進程把指令存到mem-buffer中,最后寫盤時會阻塞主進程。
3、這兩個缺點是個很大的痛點。為了解決這些痛點,GitHub的兩位工程師 Bryana Knight 和 Miguel Fernández 日前寫了一篇 文章 ,講述了將持久數據從Redis遷出的經驗:
http://www.open-open.com/lib/view/open1487736984424.html
五、如何選擇RDB和AOF
建議全都要。
1、對於我們應該選擇RDB還是AOF,官方的建議是兩個同時使用。這樣可以提供更可靠的持久化方案。
在redis 4.0 之后,官方提供了混合持久化模式,具體如下
持久化文件結構
上半段RDB格式,后半段是AOF模式。
如何配置
vim redis.conf
aof-use-rdb-preamble yes
之后重啟redis,運行bgrewriteaof命令,重寫appendonly.aof,之后在Redis數據同步的時候,可以先加載rdb的內容,然后再執行aof指令部分使Redis數據同步
數據恢復過程
加載AOF文件的入口為loadAppendOnlyFile,代碼如下
int loadAppendOnlyFile(char *filename) { ... /* Check if this AOF file has an RDB preamble. In that case we need to * load the RDB file and later continue loading the AOF tail. */ char sig[5]; /* "REDIS" */ if (fread(sig,1,5,fp) != 5 || memcmp(sig,"REDIS",5) != 0) { /* No RDB preamble, seek back at 0 offset. */ if (fseek(fp,0,SEEK_SET) == -1) goto readerr; } else { /* RDB preamble. Pass loading the RDB functions. */ rio rdb; serverLog(LL_NOTICE,"Reading RDB preamble from AOF file..."); if (fseek(fp,0,SEEK_SET) == -1) goto readerr; rioInitWithFile(&rdb,fp); if (rdbLoadRio(&rdb,NULL) != C_OK) { serverLog(LL_WARNING,"Error reading the RDB preamble of the AOF file, AOF loading aborted"); goto readerr; } else { serverLog(LL_NOTICE,"Reading the remaining AOF tail..."); } } ... }
1.打開AOF文件之后首先讀取5個字符如果是"REDIS" ,那么就說明這是一個混合持久化的AOF文件,執行rdbLoadRio() 函數,解析RDB格式,解析文件內容直至遇到RDB_OPCODE_EOF結束。
2. 執行 loadAppendOnlyFile() 函數,解析 AOF格式,直到結束整個加載過程完成。
說明:正確的RDB格式一定是以"REDIS"開頭而純AOF格式則一定以"*"開頭此時就會進入rdbLoadRio函數來加載數據。
這樣就實現了混合持久化,加載aof文件時候,實現了數據文件不太大,而且能保證數據不丟失,加載效率比純aof文件高。
本文根據視頻和博客歸納。
參考:redis,
https://yq.aliyun.com/articles/193034
感謝支持,感謝觀看。