成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

談談Redis的持久化—AOF日志與RDB快照

數據庫 其他數據庫 Redis
對于Mysql,數據是持久化在磁盤上的。如果誤刪數據,可以使用binlog進行恢復;突然宕機時,其本身可以借助redo log進行崩潰恢復。

[[429431]]

一、前言

對于Mysql,數據是持久化在磁盤上的。如果誤刪數據,可以使用binlog進行恢復;突然宕機時,其本身可以借助redo log進行崩潰恢復。

更多關于Mysql日志的內容,可以參考我的另外一篇文章數據庫日志——binlog、redo log、undo log掃盲

而對于Redis,一般是把數據直接存儲在內存中。如果不做任何持久化工作,在出現宕機后,內存中的全部數據就會丟失。

顯然,業務方是不能容忍這樣的情況發生的。好在Redis提供了一系列的持久化機制,分別是AOF日志與RDB快照。

二、AOF

AOF全稱是Append Only File,Redis每次執行完一個寫類型的語句后,會將該語句以某種格式使用追加的方式順序寫入AOF日志中。

值得注意的是,AOF是默認不開啟的。

 

[[429432]]

AOF日志的格式

以winows為例,進入到redis安裝目錄中的redis.windows.conf中,將appendonly的值修改為yes,即可開啟AOF

 

  1. # 默認關閉 
  2. appendonly yes 
  3.  
  4. # AOF的默認文件名稱 
  5. appendfilename "appendonly.aof" 

 

當執行以下命令后

 

  1. set java helloworld 

在appendonly.aof文件中,可以看到以下內容

 

  1. *3            代表當前命令有3個部分 
  2. $3            第1部分命令的長度,3個字符 
  3. set           第1部分命令 
  4. $4            第2部分命令的長度,4個字符 
  5. java          第2部分命令 
  6. $10           第3部分命令的長度,10個字符 
  7. helloworld    第3部分命令 

當我們首次使用某個客戶端執行命令時,客戶端會自動幫我們補充select 0(即選擇編號0的數據庫),這個命令也會被保存在AOF日志中。

寫AOF日志的流程

大致的流程如圖所示

 

 

 

 

在server中,主線程執行完命令之后,會立即將命令寫入AOF緩沖中。之后會調用系統函數write(),將命令寫入內核緩沖區,并返回給客戶端成功的響應。

內核會在合適的時機將內核緩沖區的中的數據寫入到磁盤中。

我們設想其中某個階段宕機時,會不會產生不一致的情況:

1、如果命令執行成功,但寫入AOF緩存前崩潰重啟,客戶端會收到執行失敗或超時的響應。重啟之后AOF文件中沒有該條數據,這個時候,數據是一致的。

2、如果命令執行成功,寫入AOF緩存成功,但調用write時崩潰重啟。其實這種情況和第一條一樣,恢復后數據還是一致的。

3、如果命令執行、寫入AOF緩存與內核緩存都成功,客戶端會收到成功的響應。如果這個時候機器宕機,內核緩沖區中的數據將會丟失,也就是最后的AOF文件缺少該條命令,恢復后,就會產生數據不一致的情況。

第3種情況發生時,就會出現數據不一致的后果。怎么處理呢,很簡單啊,變異步為同步不就行了嗎。

調用write寫入內核緩沖區后,再調用fsync強制讓內核緩沖區中的數據刷到磁盤上,刷盤成功后,再返回給客戶端響應。

這樣的解決方式看似可以,但是刷盤的操作非常耗時。在Redis執行大量命令的時候,會一直進行不斷的刷盤,當磁盤壓力過大時,會阻塞下一個命令的執行,大大降低性能。

看來得把握刷盤的時機,刷得慢了,機器崩潰恢復后就會丟失大量數據。刷得快了,就會嚴重降低性能。

不過,Redis本身也提供了3種寫回策略。

寫回策略

  • always 同步寫回。每執行一條命令,寫完AOF日志后,再返回。
  • everysec 每秒寫回。執行命令后,將數據寫入到內核緩沖區就返回。只有會有一個線程,執行每秒刷盤的定時任務。
  • no 由內核自行控制的寫回。每執行一條命令,將數據寫入到內核緩沖區就返回。內核會在合適的時機刷盤。

這3種策略體現了不同的刷盤頻率,因此擁有不同級別的一致性與性能。

always策略最大程度上保證數據不丟失,但性能最差。

no策略性能最好,但在機器崩潰重啟后會丟失比較多的數據。

everysec是一種折中的策略,較always有不錯的性能。在極端的情況下,只會丟失1秒內的數據,是比較推薦的方式。

redis.windows.conf中有appendfsync配置項,用來配置寫回策略,默認的策略是everysec 。

隨著Redis不斷記錄AOF日志,AOF日志文件將變得越來越大,用作恢復的時間也將越長。因此需要一種方式減少文件的大小,這時候AOF重寫就派上用場了。

AOF重寫

在出現觸發重寫的條件時(例如AOF文件達到某個閾值),Redis掃描整個庫的所有數據,將數據以命令的方式記錄在新的AOF日志中,待記錄完成后,使用新的AOF日志替換舊的即可。

舊日志中,可能存有對同一個key的多次操作命令,重寫的目的就是取最后一次有效的命令,刪除那些歷史命令,從而達到瘦身、壓縮的效果。

剛才提到,AOF重寫會掃描整個庫的數據,因此注定就是一個非常耗時的操作,那么就不會在主線程中做,而是通過主線程fork出一個子進程進行重寫的。

重寫的流程圖如下:

 

 

 

 

1、當AOF日志文件的大小超過執行的閾值后,就會觸發AOF重寫

2、主線程fork出一個子進程,fork的過程仍然是阻塞的。fork完之后,主線程依然可以接受命令并處理

3、子進程與主線程共享一個實例的所有數據,子進程會對整個實例進行掃描,將其中的數據以命令的格式寫入到重寫日志中。

4、在子進程重寫的過程中,主線程可以接受命令,假設這個時候執行了一條寫命令。

5、主線程會將數據存入到庫中,利用寫時復制技術,子進程不會感知到數據有任何變化。

6、主線程將日志先寫入AOF緩沖區,再寫入重寫緩沖區。

7、由特定寫回策略,將緩沖區中的數據寫入到舊的AOF日志中。

8、當子進程結束掃描,并且將所有命令寫入重寫日志后,再將重寫緩沖區中的數據追加到重寫日志中。

9、最后一步,主線程感知到子進程重寫日志完成,于是使用新的日志文件替換舊的文件。

也許有人會發出以下的疑問

為什么是fork出子進程,直接使用子線程不是也可以嗎?

如果是創建出來一個子線程,那么主線程在寫入,子線程在讀取,是需要通過加鎖的方式來保證線程安全的,加鎖就意味著降低性能。

而如果是fork出來子進程,主線程和子進程同樣需要共享數據,當主線程寫入數據的時候,會利用寫時復制技術,避免加鎖。

什么是寫時復制?

大家應該都知道三角函數吧,嗯,這和寫時復制沒什么關系。

 

[[429433]]

 

CopyOnWriteArrayList就利用到了寫時復制,讀不加鎖,寫則是復制一份數組出來,在新的數組上進行修改,最后替換引用。非常適合應用于讀多寫少的場景,缺點是在替換引用前,線程讀到的是舊數據。

主線程在fork出一個子進程的時候,會將自己的頁表(虛擬地址與物理地址的映射表)復制一份出來給子進程,而不是直接復制內存。否則在重寫的時候,Redis占用內存會立即翻倍。

這樣的話,子進程就可以隨意訪問主線程中的數據。而當主線程修改一些實例數據時,就會復制一份物理內存出來,并變動主線程的頁表,在新的內存地址上存儲寫之后的數據。因為沒有變動子進程的頁表,因此主線程寫入的數據對子進程不可見。

重寫AOF緩沖區的作用是什么?

CopyOnWriteArrayList的缺點在于讀到的可能是舊數據,子進程在掃描的時候,其實掃描到的也是舊數據,因此需要在重寫結束后做補償。

子進程在重寫的過程中,掃描的數據是fork動作結束的那一刻的快照。而在重寫的過程中,主線程依然可以執行命令,那么這些多出來的寫命令就可以放在一個獨立的重寫緩沖區中。在重寫完成后,再將重寫緩沖區中的內容追加到重寫日志中,這就保證了數據的一致。

盡管存在AOF重寫機制,但重寫后的日志文件還是大,恢復速度較慢。

有沒有一種直接存儲數據,而不是存儲命令(命令的大小顯然大于數據本身)的方式呢?RDB就閃亮登場了!

三、RDB

RDB的全稱是Redis Database Backup,即數據備份。

會將某一時刻內的所有數據生成一個快照文件。該文件是一種經過壓縮的二進制文件,默認名稱為dump.rdb,可通過修改dbfilename參數來改變RDB文件名。

快照文件僅保存數據,不保存額外的操作命令,且經過壓縮,因此在恢復速度上快于AOF。但RDB沒法做到實時的持久化,而AOF可以基本做到。

如何讓Redis生成RDB文件

通過save命令手動觸發

直接在主線程中執行,會阻塞其他命令

通過bgsave命令手動觸發

主線程fork出來一個子進程,由子進程去執行備份。

整個fork的過程,是會阻塞主線程的。由于不會復制物理內存,因此fork是快速的。

fork結束后,主線程依然可以執行其他的命令。

通過配置自動觸發

redis.windows.conf中有如下的幾個配置可用于觸發生成RDB文件

 

  1. # 900秒內至少出現1條寫命令就觸發 
  2. save 900 1 
  3.  
  4. # 300秒內至少出現10條寫命令就觸發 
  5. save 300 10 
  6.  
  7. # 60秒內至少出現10000條寫命令就觸發 
  8. save 60 10000 

 

這種方式,也是通過fork出一個子進程來做的。

三種方式的觸發流程

 

 

 

 

客戶端使用bgsave命令時,主線程fork出來子進程,由子進程完成備份。

在子進程備份期間,主線程依然可以執行命令。但該條數據并不會被子進程掃描到,和AOF重寫一樣,都利用到了寫時復制。

既然RDB文件占用小,恢復速度快,那可以大幅增加RDB生成的頻率嗎?

那顯然是不可以的,有可能上一輪RDB還未生成,下一輪又開始了。而且也存在性能問題,save全程都會阻塞主線程,bgsave的fork操作同樣也會阻塞主線程。

當然,RDB這種方式,如果在持久化的過程中發生宕機,會丟失在上次備份之后產生的所有數據。

四、AOF與RDB的特點總結

下面使用一張表格來直觀地展示兩者之間的優缺點

 

 

另外值得注意的是,當同時開啟AOF與RDB時,Redis會優先使用AOF日志來恢復數據。

RDB相比而言,會丟失較多的數據。AOF只有在實例數據比較大的時候,恢復速度才慢。

五、Redis4.0混合持久化模式

既然AOF與RDB獨有各自的優勢,能否結合二者的特點呢?

在Redis4.0中,出現了一個新的模式——混合持久化。具體來講,就是全量RDB+增量AOF,將兩種類型的日志文件存放在一起。

RDB可以以較低的頻率執行,兩次RDB之間的產生的增量數據記錄在AOF日志中,因此增量AOF日志的文件很小。

 

因此Redis在恢復時,先加載RDB數據,再重放增量的AOF日志。不需要像之前重放全量AOF日志,因此恢復效率大大提升。

 

責任編輯:姜華 來源: 今日頭條
相關推薦

2023-03-13 08:08:48

數據庫Redis

2021-07-18 07:59:42

RedisRDBAOF

2023-05-11 09:12:35

RedisRDB日志

2024-09-12 08:49:53

2024-03-26 00:03:08

Redis數據RDB

2024-09-06 17:49:46

2019-05-17 08:55:49

RedisRDBAOF

2024-09-29 09:25:53

2021-03-10 00:02:01

Redis

2025-01-16 14:03:35

Redis

2020-01-06 14:54:31

RDBAOFRedis

2024-11-22 08:31:32

Redis數據持久化高可用

2024-12-20 12:15:06

RedisRDB持久化

2021-01-05 10:48:38

RedisAOF日志RDB快照

2021-02-04 08:01:35

RedisRDBAOF

2020-12-11 11:40:37

RDBAOFRedis

2023-10-12 13:01:29

Redis數據庫

2025-03-14 08:00:00

AOFRedis數據庫

2023-10-23 11:22:06

Redis數據持久化

2012-03-07 09:18:06

Redis
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产激情毛片 | 成人午夜av| 一区二区三区国产精品 | 欧美精品一区二区免费 | 亚洲综合久久久 | www.久草 | 91精品久久久久久久久中文字幕 | 欧美日韩一区在线 | 九九热热九九 | 九九热热九九 | 国产japanhdxxxx麻豆 | 日韩一区二区三区视频 | a久久| 视频一区二区国产 | 亚欧精品一区 | www.国产精 | 亚洲精品在线看 | 国产欧美综合在线 | 免费三级网站 | 国产一区二区三区 | 日韩一区二区三区在线播放 | 久久伊人青青草 | 免费能直接在线观看黄的视频 | 欧美在线一区二区三区 | 91在线网站 | 欧美综合久久 | 免费在线成人 | 成人av播放| 国产精品五月天 | 免费在线一区二区三区 | 国产激情精品 | 国产在线精品一区二区三区 | 中文字幕电影在线观看 | 日韩不卡在线 | 天天操夜夜操免费视频 | 久久久久久免费毛片精品 | 日韩三极 | 免费观看一级特黄欧美大片 | 国产丝袜一区二区三区免费视频 | 免费久草 | 午夜影院在线观看 |