<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何快速實(shí)現(xiàn) Redis 持久化

          共 10669字,需瀏覽 22分鐘

           ·

          2023-08-19 00:54

          本文轉(zhuǎn)載自:「Se7en的架構(gòu)筆記」
          原文:https://url.hi-linux.com/KpXwe

          RDB快照(Redis DataBase)

          RDB是一種快照存儲持久化方式,具體就是將Redis某一時(shí)刻的內(nèi)存數(shù)據(jù)保存到硬盤的文件當(dāng)中,默認(rèn)保存的文件名為dump.rdb,而在Redis服務(wù)器啟動時(shí),會重新加載dump.rdb文件的數(shù)據(jù)到內(nèi)存當(dāng)中恢復(fù)數(shù)據(jù)。

          開啟RDB持久化方式

          開啟RDB持久化方式很簡單,客戶端可以通過向Redis服務(wù)器發(fā)送save或bgsave命令讓服務(wù)器生成rdb文件,或者通過服務(wù)器配置文件指定觸發(fā)RDB條件。每次執(zhí)行都會將所有redis內(nèi)存快照到一個(gè)新的rdb文件里,并覆蓋原有rdb快照文件。

          方式一:save命令

          # 同步數(shù)據(jù)到磁盤上
          > save 

          當(dāng)客戶端向服務(wù)器發(fā)送save命令請求進(jìn)行持久化時(shí),服務(wù)器會阻塞save命令之后的其他客戶端的請求,直到數(shù)據(jù)同步完成。 如果數(shù)據(jù)量太大,同步數(shù)據(jù)會執(zhí)行很久,而這期間Redis服務(wù)器也無法接收其他請求,所以,最好不要在生產(chǎn)環(huán)境使用save命令。

          方式二:bgsave命令

          # 異步保存數(shù)據(jù)集到磁盤上
          > bgsave
          • 當(dāng)客戶端發(fā)服務(wù)發(fā)出bgsave命令時(shí),Redis服務(wù)器主進(jìn)程會forks一個(gè)子進(jìn)程來解決數(shù)據(jù)同步問題,在將數(shù)據(jù)保存到rdb文件之后,子進(jìn)程會退出。
          • 所以,與save命令相比,Redis服務(wù)器在處理bgsave采用子線程進(jìn)行IO寫入,而主進(jìn)程仍然可以接收其他請求,但forks子進(jìn)程是同步的,所以forks子進(jìn)程時(shí),一樣不能接收其他請求,這意味著,如果forks一個(gè)子進(jìn)程花費(fèi)的時(shí)間太久(一般是很快的),bgsave命令仍然有阻塞其他客戶的請求的情況發(fā)生。
          • 我們可以控制單個(gè)Redis實(shí)例的最大內(nèi)存,來盡可能降低Redis在fork時(shí)的事件消耗。以及上面提到的自動觸發(fā)的頻率減少fork次數(shù),或者使用手動觸發(fā),根據(jù)自己的機(jī)制來完成持久化。

          方式三:通過配置文件自動觸發(fā)

          自動觸發(fā)的場景主要是有以下幾點(diǎn):

          • 1.根據(jù)我們的 save m n 配置規(guī)則自動觸發(fā);
          • 2.從節(jié)點(diǎn)全量復(fù)制時(shí),主節(jié)點(diǎn)發(fā)送rdb文件給從節(jié)點(diǎn)完成復(fù)制操作,主節(jié)點(diǎn)會觸發(fā) bgsave;
          • 3.執(zhí)行 debug reload 時(shí);
          • 4.執(zhí)行shutdown時(shí),如果沒有開啟aof,也會觸發(fā)。

          這里我們講的是根據(jù)配置文件自動觸發(fā):

          # 時(shí)間策略
          #關(guān)閉RDB只需要將所有的save保存策略注釋掉即可
          save 900 1   #900s內(nèi)如果有1條數(shù)據(jù)寫入,就產(chǎn)生RDB快照
          save 300 10 #300s內(nèi)有10條數(shù)據(jù)寫入,就產(chǎn)生RDB快照 
          save 60 10000  #60s內(nèi)如果有10000條數(shù)據(jù)寫入,就產(chǎn)生RDB快照

          # 文件名稱
          dbfilename dump.rdb

          # 文件保存路徑
          dir /var/lib/redis/6379

          # 如果持久化出錯,主進(jìn)程是否停止寫入
          stop-writes-on-bgsave-error yes

          # 是否壓縮
          # 建議沒有必要開啟,畢竟Redis本身就屬于CPU密集型服務(wù)器,再開啟壓縮會帶來更多的CPU消耗,相比硬盤成本,CPU更值錢。
          rdbcompression no

          # 導(dǎo)入時(shí)是否檢查
          rdbchecksum yes

          save和bgsave對比

          配置文件自動生成rdb文件后臺使用的是bgsave方式。

          RDB文件

          前面介紹了三種讓服務(wù)器生成rdb文件的方式,無論是由主進(jìn)程生成還是子進(jìn)程來生成,其過程如下:

          • 生成臨時(shí)rdb文件,并寫入數(shù)據(jù)。
          • 完成數(shù)據(jù)寫入,用臨時(shí)文件替代正式rdb文件。
          • 刪除原來的db文件。

          COW寫時(shí)復(fù)制(copy-on-write)

          fork創(chuàng)建出的子進(jìn)程,與父進(jìn)程共享內(nèi)存空間。也就是說,如果子進(jìn)程不對內(nèi)存空間進(jìn)行寫入操作的話(Redis的子進(jìn)程只做數(shù)據(jù)落盤的操作,也不會去寫數(shù)據(jù)),內(nèi)存空間中的數(shù)據(jù)并不會復(fù)制給子進(jìn)程,這樣創(chuàng)建子進(jìn)程的速度就很快了!(不用復(fù)制,直接引用父進(jìn)程的物理空間,玩的是指針)。

          當(dāng)Redis父進(jìn)程修改數(shù)據(jù)時(shí),父進(jìn)程會將原先的數(shù)據(jù)復(fù)制一份生成新的副本,然后修改父進(jìn)程的指針,指向新的數(shù)據(jù),此時(shí)父進(jìn)程修改的新的數(shù)據(jù)不會影響到子進(jìn)程。此時(shí)子進(jìn)程的指針仍然指向舊的數(shù)據(jù),子進(jìn)程看到的數(shù)據(jù)還是bgsave時(shí)候的數(shù)據(jù)。當(dāng)下一次執(zhí)行bgsave時(shí),新fork出來的子進(jìn)程指針才會指向這次新的數(shù)據(jù)。

          AOF(append-only file)

          與RDB存儲某個(gè)時(shí)刻的快照不同,AOF持久化方式會記錄客戶端對服務(wù)器的每一次寫操作命令,并將這些寫操作以追加的方式保存到以后綴為aof文件中,在Redis服務(wù)器重啟時(shí),會加載并運(yùn)行aof文件的命令,以達(dá)到恢復(fù)數(shù)據(jù)的目的。

          開啟AOF持久化的方式

          方式一:bgrewriteaof命令

          > bgrewriteaof

          方式二:通過配置文件自動觸發(fā)

          Redis默認(rèn)不開啟AOF持久化方式,我們可以在配置文件中開啟并進(jìn)行更加詳細(xì)的配置:

          #開啟aof
          appendonly yes

          # 文件名稱
          appendfilename "appendonly.aof"

          # 同步方式
          #appendfsync always #每次有新命令追加到 AOF 文件時(shí)就執(zhí)行一次 fsync ,非常慢,也非常安全。 
          appendfsync everysec #默認(rèn)方式,每秒 fsync 一次,足夠快,并且在故障時(shí)只會丟失 1 秒鐘的數(shù)據(jù)。
          #appendfsync no  #從不 fsync ,將數(shù)據(jù)交給操作系統(tǒng)來處理。更快,也更不安全的選擇。

          重寫

          AOF將客戶端的每一個(gè)寫操作都追加到aof文件末尾,比如對一個(gè)key多次執(zhí)行incr命令,這時(shí)候,aof保存每一次命令到aof文件中,aof文件會變得非常大。

          127.0.0.1:6379> INCR readcount
          (integer) 1
          127.0.0.1:6379> INCR readcount
          (integer) 2
          127.0.0.1:6379> INCR readcount
          (integer) 3
          127.0.0.1:6379> INCR readcount
          (integer) 4
          127.0.0.1:6379> INCR readcount
          (integer) 5

          這是一種resp協(xié)議格式數(shù)據(jù),星號后面的數(shù)字代表命令有多少個(gè)參數(shù),$號后面的數(shù)字代表這個(gè)參數(shù)有幾個(gè)字符

          [root@redis 6379]# cat appendonly.aof
          *2
          $6
          SELECT
          $1
          0
          *2
          $4
          INCR
          $9
          readcount
          *2
          $4
          INCR
          $9
          readcount
          *2
          $4
          INCR
          $9
          readcount
          *2
          $4
          INCR
          $9
          readcount
          *2
          $4
          INCR
          $9
          readcount

          手動執(zhí)行重寫命令BGREWRITEAOF:

          127.0.0.1:6379> BGREWRITEAOF
          Background append only file rewriting started

          重寫后AOF文件里如下,將多個(gè)incr命令進(jìn)行了合并

          [root@redis 6379]# cat appendonly.aof
          *2
          $6
          SELECT
          $1
          0
          *3
          $3
          SET
          $9
          readcount
          $1
          5

          重寫配置參數(shù)

          AOF重寫redis會fork出一個(gè)子進(jìn)程去做(與bgsave命令類似),不會對redis正常命令處理有太多影響:

          auto‐aof‐rewrite‐min‐size 64mb #aof文件至少要達(dá)到64M才會自動重寫,文件太小恢復(fù)速度本來就 很快,重寫的意義不大
          auto‐aof‐rewrite‐percentage 100 #aof文件自上一次重寫后文件大小增長了100%則再次觸發(fā)重寫,例如上一次重寫的大小是64M,那么下一次達(dá)到128M再做重寫

          AOF重寫流程圖

          • 在重寫期間,由于主進(jìn)程依然在響應(yīng)命令,為了保證最終備份的完整性;因此它依然會寫入舊的AOF file中,如果重寫失敗,能夠保證數(shù)據(jù)不丟失。
          • 為了把重寫期間響應(yīng)的寫入信息也寫入到新的文件中,因此也會為子進(jìn)程保留一個(gè)buf,防止新寫的file丟失數(shù)據(jù)。
          • 重寫是直接把當(dāng)前內(nèi)存的數(shù)據(jù)生成對應(yīng)命令,并不需要讀取老的AOF文件進(jìn)行分析、命令合并。
          • 不管是RDB還是AOF都是先寫入一個(gè)臨時(shí)文件,然后通過 rename 完成文件的替換工作。


          混合持久化

          重啟 Redis 時(shí),我們很少使用 RDB來恢復(fù)內(nèi)存狀態(tài),因?yàn)闀G失大量數(shù)據(jù)。我們通常使用 AOF 日志重放,但是重放 AOF 日志性能相對 RDB來說要慢很多,這樣在 Redis 實(shí)例很大的情況下,啟動需要花費(fèi)很長的時(shí)間。Redis 4.0 為了解決這個(gè)問題,帶來了一個(gè)新的持久化選項(xiàng)——混合持久化。通過如下配置可以開啟混合持久化(前提必須先開啟aof):

          aof‐use‐rdb‐preambleyes #開啟混合持久化

          如果開啟了混合持久化,AOF在重寫時(shí),不再是單純將內(nèi)存數(shù)據(jù)轉(zhuǎn)換為RESP命令寫入AOF文件,而是將重寫這一刻之前的內(nèi)存做RDB快照處理,并且將RDB快照內(nèi)容和增量的AOF修改內(nèi)存數(shù)據(jù)的命令存在一起,都寫入新的AOF文件,新的文件一開始不叫appendonly.aof,等到重寫完新的AOF文件才會進(jìn)行改名,覆蓋原有的AOF文件,完成新舊兩個(gè)AOF文件的替換。于是在 Redis 重啟的時(shí)候,可以先加載 RDB 的內(nèi)容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重啟效率大幅得到提升。

          127.0.0.1:6379> set k 1
          OK
          127.0.0.1:6379> set k 2
          OK
          127.0.0.1:6379> BGREWRITEAOF
          Background append only file rewriting started

          查看此時(shí)的appendonly.aof文件:此時(shí)存放的是RDB的內(nèi)容

          [root@redis 6379]# cat appendonly.aof
          REDIS0009? redis-ver5.0.7?
          ?edis-bits?@?ctime?%y?_used-mem??
           aof-preamble???k? readcount?? R??i9$?[root@redis 6379]#

          如果新增加了數(shù)據(jù):

          127.0.0.1:6379> set k 3
          OK

          那么新的數(shù)據(jù)會以為RESP命令的方式追加在后面:

          [root@redis 6379]# cat appendonly.aof
          REDIS0009? redis-ver5.0.7?
          ?edis-bits?@?ctime?%y?_used-mem??
           aof-preamble???k? readcount?? R??i9$?*2
          $6
          SELECT
          $1
          0
          *3
          $3
          set
          $1
          k
          $1
          3

          混合持久化AOF文件結(jié)構(gòu)如下:

          從持久化中恢復(fù)數(shù)據(jù)

          數(shù)據(jù)的備份、持久化做完了,我們?nèi)绾螐倪@些持久化文件中恢復(fù)數(shù)據(jù)呢?如果一臺服務(wù)器上有既有RDB文件,又有AOF文件,該加載誰呢?

          其實(shí)想要從這些文件中恢復(fù)數(shù)據(jù),只需要重新啟動Redis即可。我們還是通過圖來了解這個(gè)流程:

          啟動時(shí)會先檢查AOF文件是否存在,如果不存在就嘗試加載RDB。那么為什么會優(yōu)先加載AOF呢?因?yàn)锳OF保存的數(shù)據(jù)更完整,通過上面的分析我們知道AOF基本上最多損失1s的數(shù)據(jù)。

          RBD和AOF對比

          另外RBD不支持拉鏈,只有一個(gè)dump.rdb文件。


                   
                   
          往期推薦

           

                         
                         
                          
                          
                             
                             
               
               
                   
                   
                     
                     

                       
                       

          點(diǎn)亮,服務(wù)器三年不宕機(jī)

          瀏覽 1405
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品秘 | 色导航 | 色色色色五月天 | 91电影在线 亚洲精品 | 婷婷五月丁香亚洲 |