Redis(二)、Redis持久化RDB和AOF

1、Redis兩種持久化方式

對Redis而言,其數據是保存在內存中的,一旦機器宕機,內存中的數據會丟失,所以須要將數據異步持久化到硬盤中保存。這樣,即便機器宕機,數據能從硬盤中恢復。html

常見的數據持久化方式:linux

1.快照:相似拍照記錄時光,快照是某時某刻將數據庫的數據作拍照記錄下其數據信息。如MYSQL的Dump,Redis的RDB模式redis

2.寫日誌方式:是將數據的操做所有寫到日誌當中,須要恢復的時候,按照日誌記錄的操做記錄從新再執行一遍。例如MYSQL的Binlog,Redis的AAOF模式、數據庫

 

2、RDB

說明:

redis默認開啓,將redis在內存中保存的數據,以快照的方式持久化到硬盤中保存。vim

觸發機制:

1.save命令:阻塞方式,須要等redis執行完save後,才能執行其餘get、set等操做。同步方式安全

2.bgsave命令:非阻塞,其原理是調用linux 的  fork()函數,建立redis的子進程,子進程進行建立  rdb 文件的操做。異步方式,app

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 的持久化和數據的恢復要選擇在夜深人靜的時候執行是比較合理的。

 

3、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中,最後寫盤時會阻塞主進程。

 

4、關於Redis持久化方式RDB和AOF的缺點

緣由是redis持久化方式的痛點,缺點比較明顯。

一、RDB須要定時持久化,風險是可能會丟兩次持久之間的數據,量可能很大。

二、AOF每秒fsync一次指令硬盤,若是硬盤IO慢,會阻塞父進程;風險是會丟失1秒多的數據;在Rewrite過程當中,主進程把指令存到mem-buffer中,最後寫盤時會阻塞主進程。

三、這兩個缺點是個很大的痛點。爲了解決這些痛點,GitHub的兩位工程師 Bryana Knight 和 Miguel Fernández 日前寫了一篇 文章 ,講述了將持久數據從Redis遷出的經驗:

 http://www.open-open.com/lib/view/open1487736984424.html

5、如何選擇RDB和AOF

建議全都要。

一、對於咱們應該選擇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

 感謝支持,感謝觀看。

相關文章
相關標籤/搜索