一文掌握Redis持久化

Redis持久化

Redis常用作KV緩存,熱點數據都在內存、訪問速度極快。
但誰也不能保證服務的100%可用,意外宕機內存中的數據就沒了,對一些數據敏感的業務勢必會造成影響。
因此,Redis提供了持久化,目的就是將內存中的數據儘量保存到磁盤上來,同時最大可能的不影響原本高性能的讀寫操作。

1、Redis提供了兩種持久化的方式,分別是RDB(Redis DataBase)和AOF(Append Only File)。
Redis 默認開啓了rdb。啓動redis-server後,自動生成dump.rdb文件(默認在Redis啓動目錄下)。
2、RDB,簡而言之,就是在不同的時間點,將redis存儲的數據生成快照並存儲到磁盤等介質上;就像Word文檔定時自動保存功能,防止數據丟失。
3、AOF,則是換了一個角度來實現持久化,那就是將redis執行過的所有寫指令記錄下來,在下次redis重新啓動時,只要把這些寫指令執行一遍,就可以實現數據恢復了。
4、其實RDB和AOF兩種方式也可以同時使用,在這種情況下,如果redis重啓的話,則會優先採用AOF方式來進行數據恢復,這是因爲AOF方式的數據恢復完整度更高。

RDB

Redis 默認開啓了rdb持久化。啓動redis-server後,自動生成dump.rdb快照文件(默認在Redis啓動目錄下)。
redis啓動時,會先加載dump.rdb文件,將磁盤快照加載到Redis內存中。
redis-server啓動、指定redis.conf時,redis.conf內配置的dir選項,指定了.rdb快照文件的路徑。

什麼時候,會觸發rdb持久化?

1、shutdown(正常關閉)時,如果沒有開啓aof,會觸發;
kill -9 意外宕機不會觸發rdb持久化;
2、redis.conf默認配置(此配置是針對bgsave):

	save 900 1	#900s檢查一次,增量的數據變更命令超過1,就觸發;
	save 300 10	#300s 更改10次
	sava 60 10000 #60s 更改命令1w條,就觸發;

根據這個默認配置,會丟數據;意外宕機的情況下,丟失最後一次持久化後的數據

ps:如果rdb和aof都開啓,一般留第一條開啓就行(開啓aof時,rdb快照沒必要這麼頻繁)。
前兩種都是redis自動觸發,底層都是bgsave;

3、執行命令save或者bgsave

  • save是隻管保存,其他不管,全部阻塞(持久化是用的主進程,不會fork子進程);
  • bgsave redis會在後臺異步進行快照操作(fork子進程),同時可以響應客戶端的請求;

4、執行flushall命令,清空rdb(Redis默認16個庫都清空);但是裏面是空的,無意義

數據遷移,就是基於.rdb快照文件;slave獲取到主庫的.rdb文件後,如何加載?

1、cp拷貝過來的dump500000.rdb,改名成默認dump.rdb;自動bgsave就加載了該rdb文件。
2、修改redis.conf配置 dbfilename dump.rdb;將文件名配置成成cp來的;

演示1:手動執行bgsave, 同時在另一個終端立即ps -ef|grep redis 查看進程,可以看到fork子進程redis-rdb-bgsave;

演示2:手動執行save,手動觸發rdb持久化;另一個redis-cli執行set 寫請求 會被阻塞(3.9s才返回)。
因爲save是用主進程進程快照保存,沒有fork子進程。

結論:
正常rdb持久化(自動觸發) 會fork一個子進程進行;
所以rdb持久化不會阻塞用戶請求;只會在fork()系統調用時,阻塞一瞬間;

關於dump.rdb文件

.rdb文件,是保存的二進制數據文件,人是看不懂的。二進制文件較爲緊湊,500w個簡單kv的.rdb文件約90M。
觸發rdb持久化時,會生成新的臨時dump-xxx.rdb文件,執行完成再替換舊的。
Redis調優,就是根據業務情況,選擇合理的rdb觸發頻率,而非一味的進行持久化。

rdb持久化與Redis主從同步

redis主從複製,rdb持久化不能關閉;
從機是基於主機的rdb實現主從複製。

RDB優缺點

優點:
二進制、備份和還原速度快;適合大量數據的同步遷移、備份(異地跨機房數據遷移);
自動觸發rdb保存快照,會fork子進程,不會阻塞用戶請求;
缺點:意外宕機時,丟失數據有點多。意外宕機的情況下,丟失最後一次持久化後的數據。

AOF

aof保存每條指令的RESP協議串。什麼是RESP,參見:
aof文件是可以看得懂的,因爲RESP指令是近似明文的文本。

aof觸發機制(根據redis.conf配置項)
  • no:表示等操作系統進行數據緩存同步到磁盤(快,持久化沒保證)
  • always:同步持久化,每次發生數據變更時,立即記錄到磁盤(慢,安全)
  • everysec:表示每秒同步一次(默認值,很快,但可能會丟失一秒以內的數據)

always選項,在prod幾乎不會用。
redis-server啓動後,1秒鐘,就會產生appendonly.aof文件,因爲默認everysec;

AOF重寫

appendonly.aof 不斷追加變大,文件變大會使io效率降低。
要解決這個問題,出現重寫(bgrewriteaof),就是給aof文件瘦身。

bgrewriteaof 瘦身-觸發時機

1、自動觸發重寫

auto-aof-rewrite-min-size 64m	默認超過64m就重寫,prod一般配成幾個G。重寫也是耗性能的。
auto-aof-rewrite-percentage 100

2、手動執行bgrewriteaof 瘦身命令;

ps:prod環境,一般auto-aof-rewrite-min-size 不會小於3G;
aof重寫也是fork子進程的,沒必要產生這塊性能開銷,Redis調優就是調這些地方。

aof重寫,是怎樣識別這個命令有沒有用呢?

比如一串命令操作:

set abc 2019
set abc 2020
set abc 2021

set bcd 2019
set bcd 2020
set bcd 2021

我們知道,aof重寫之後,最終aof文件只保留了最終的數據,也就是abc=2021,bcd=2021,其他被覆蓋的無效命令就去除了。
這個重寫過程,如何知道去除哪些指令、和保留哪些呢?
Redis也沒有高超的辦法,就是和內存的數據比對(保留哪些指令),這是aof重寫消耗性能的根源。

RDB或AOF文件意外損壞可以恢復嗎

可以使用Redis安裝目錄下的工具:redis-check-aof/redis-check-rdb
在這裏插入圖片描述

Redis4.0+混合持久化機制
bgrewriteaof重寫之後,appendonly.aof文件變成:
-bitsÀ@ú^EctimeÂíÛ×]ú^Hused-mem°^E^M^@ú^Laof-preambleÀ^Aþ^@û^A^@^@^Bk2^Bv1ÿR^B^TÑQ;ED

appendonly.aof文件,變成不可讀的了???這是怎麼回事,前面不是說aof文件保存的是每一條RESP指令,是可讀的嗎?
這和版本有關,5.0之後默認開啓混合持久化;aof重寫後、可能包含rdb二進制數據。
重寫完成後的appendonly.aof,後續增量命令,還會以aof方式追加。

開啓混合持久化

4.0版本的混合持久化默認關閉的,通過aof-use-rdb-preamble配置參數控制,yes則表示開啓,no表示禁用,5.0之後默認開啓。
混合持久化是通過bgrewriteaof完成的,不同的是當開啓混合持久化時,fork出的子進程先將共享的內存副本全量的以RDB方式寫入aof文件,然後在將重寫緩衝區的增量命令以AOF方式寫入到文件,寫入完成後通知主進程更新統計信息,並將新的含有RDB格式和AOF格式的AOF文件替換舊的的AOF文件。簡單的說:新的AOF文件前半段是RDB格式的全量數據後半段是AOF格式的增量數據,

混合持久化優缺點

優點:混合持久化結合了RDB持久化 和 AOF 持久化的優點, 由於絕大部分都是RDB格式,加載速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。
缺點:兼容性差,一旦開啓了混合持久化,在4.0之前版本都不識別該aof文件,同時由於前部分是RDB格式,閱讀性較差

本文首發於公衆號 架構道與術(ToBeArchitecturer),歡迎關注、學習更多幹貨~
在這裏插入圖片描述

發佈了208 篇原創文章 · 獲贊 609 · 訪問量 114萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章