<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>

          關(guān)于Redis持久化需要了解的

          共 6339字,需瀏覽 13分鐘

           ·

          2022-01-17 00:02


          相關(guān)閱讀

          300本計算機編程的經(jīng)典書籍下載

          AI全套:Python3+TensorFlow打造人臉識別智能小程序

          最新人工智能資料-Google工程師親授 Tensorflow-入門到進(jìn)階

          Java架構(gòu)全階段七期完整

          黑馬頭條項目 - Java Springboot2.0(視頻、資料、代碼和講義)14天完整版

          Spring核心編程思想

          2T架構(gòu)師學(xué)習(xí)資料干貨分享

          作者:等不到的口琴
          來源:cnblogs.com/Courage129/p/14342102.html


          Redis是一個鍵值對數(shù)據(jù)庫服務(wù)器,由于Redis是內(nèi)存數(shù)據(jù)庫,那么有很多內(nèi)存的特點,例如掉電易失,或者進(jìn)程退出,服務(wù)器中的數(shù)據(jù)也將消失不見,所以需要一種方法將數(shù)據(jù)從內(nèi)存中寫到磁盤,這一過程稱之為數(shù)據(jù)持久化。

          持久化有兩種方式,一種是RDB,操作手段是將數(shù)據(jù)從內(nèi)存中寫到磁盤,生成一個經(jīng)過壓縮的RDB文件,另一種持久化方式叫AOF,是把Redis執(zhí)行的命令行逐句記錄下來,追加在類似日志的文件中。

          RDB持久化

          Redis中有兩個命令可以用來生成RDB文件,一個是SAVE,另一個是BGSAVE
          SAVE是線程阻塞的,當(dāng)調(diào)用這個命令后,服務(wù)器不再對外提供服務(wù),直到內(nèi)存中需要存儲的數(shù)據(jù)全都持久化為RDB文件。
          bgsavesave不同,bgsave會創(chuàng)建一個子線程來完成數(shù)據(jù)持久化的任務(wù),主服務(wù)器依舊對外提供服務(wù)。
          無論是哪種方式,底層都是調(diào)用同一個函數(shù)rdb.c/rdbSave()來完成,下面是二者實現(xiàn)的偽代碼:


          def save():  rdbSave()


          def BGSAVE():  # 創(chuàng)建子進(jìn)程  pid = fork()        if pid == 0:      # 子進(jìn)程創(chuàng)建RDB文件      rdbSave()            # 完成之后向父進(jìn)程發(fā)送信號             signal_parent()         if pid > 0             # 父進(jìn)程繼續(xù)處理請求,并通過輪詢等待子進(jìn)程的信號             handle_request_and_wait_signal()         else:         # 處理出錯情況       handle_fork_error()


          和創(chuàng)建RDB文件不同的是,RDB文件的載入是在服務(wù)器啟動時自動執(zhí)行的,所以Redis并沒有專門用于載入RDB文件的命令,只要Redis服務(wù)器在啟動時檢測到RDB文件的存在,就會自動載入。
          另外值得一提的是,因為AOF文件的更新頻率通常比RDB文件的更新頻率高,所以:如果服務(wù)器開啟了AOF持久化功能,那么服務(wù)器會優(yōu)先使用AOF文件來還原數(shù)據(jù)庫狀態(tài)。只有在AOF持久化功能處于關(guān)閉狀態(tài)時,服務(wù)器才會使用RDB文件來還原數(shù)據(jù)庫狀態(tài)。
          因為BGSAVE命令可以在不阻塞服務(wù)器進(jìn)程的情況下執(zhí)行,所以Redis允許用戶通過設(shè)置服務(wù)器配置的save選項,讓服務(wù)器每隔一段時間自動執(zhí)行一次BGSAVE命令。也可以通過啟動Redis服務(wù)器時,將這些配置信息保存進(jìn)對應(yīng)的.conf
          如果持久化配置如下:


          save?900?1
          save?300?10
          save?60?10000


          那么只要滿足以下三個條件中的任意一個,BGSAVE命令就會被執(zhí)行:

          服務(wù)器在900秒之內(nèi),對數(shù)據(jù)庫進(jìn)行了至少1次修改。

          服務(wù)器在300秒之內(nèi),對數(shù)據(jù)庫進(jìn)行了至少10次修改。

          服務(wù)器在60秒之內(nèi),對數(shù)據(jù)庫進(jìn)行了至少10000次修改。

          RDB文件結(jié)構(gòu)

          db_version長度為4字節(jié),它的值是一個字符串表示的整數(shù),這個整數(shù)記錄了RDB文件的版本號,比如"0006"就代表RDB文件的版本為第六版。本章只介紹第六版RDB文件的結(jié)構(gòu)。

          databases部分包含著零個或任意多個數(shù)據(jù)庫,以及各個數(shù)據(jù)庫中的鍵值對數(shù)據(jù):如果服務(wù)器的數(shù)據(jù)庫狀態(tài)為空(所有數(shù)據(jù)庫都是空的),那么這個部分也為空,長度為0字節(jié)。·如果服務(wù)器的數(shù)據(jù)庫狀態(tài)為非空(有至少一個數(shù)據(jù)庫非空),那么這個部分也為非空,根據(jù)數(shù)據(jù)庫所保存鍵值對的數(shù)量、類型和內(nèi)容不同,這個部分的長度也會有所不同。

          EOF常量的長度為1字節(jié),這個常量標(biāo)志著RDB文件正文內(nèi)容的結(jié)束,當(dāng)讀入程序遇到這個值的時候,它知道所有數(shù)據(jù)庫的所有鍵值對都已經(jīng)載入完畢了。

          check_sum是一個8字節(jié)長的無符號整數(shù),保存著一個校驗和,這個校驗和是程序通過對REDIS、db_version、databases、EOF四個部分的內(nèi)容進(jìn)行計算得出的。服務(wù)器在載入RDB文件時,會將載入數(shù)據(jù)所計算出的校驗和與check_sum所記錄的校驗和進(jìn)行對比,以此來檢查RDB文件是否有出錯或者損壞的情況出現(xiàn)。

          AOF持久化

          除了RDB持久化功能之外,Redis還提供了AOF(Append Only File)持久化功能。與RDB持久化通過保存數(shù)據(jù)庫中的鍵值對來記錄數(shù)據(jù)庫狀態(tài)不同,AOF持久化是通過保存Redis服務(wù)器所執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài)的,如圖所示:

          如果我們對空白的數(shù)據(jù)庫執(zhí)行以下寫命令,那么數(shù)據(jù)庫中將包含三個鍵值對:


          redis>?SET?msg?"hello"?OK?redis>?SADD?fruits?"apple"?"banana"?"cherry"?(integer)?3?redis>?RPUSH?numbers?128?256?512?(integer)?3


          RDB持久化保存數(shù)據(jù)庫狀態(tài)的方法是將msg、fruits、numbers三個鍵的鍵值對保存到RDB文件中,而AOF持久化保存數(shù)據(jù)庫狀態(tài)的方法則是將服務(wù)器執(zhí)
          另外搜索公眾號互聯(lián)網(wǎng)架構(gòu)師回復(fù)關(guān)鍵字"2T”獲取一份驚喜禮包。
          行的SET、SADD、RPUSH三個命令保存到AOF文件中。被寫入AOF文件的所有命令都是以Redis的命令請求協(xié)議格式保存的,因為Redis的命令請求協(xié)議是純文本格式,所以我們可以直接打開一個AOF文件,觀察里面的內(nèi)容。例如,對于之前執(zhí)行的三個寫命令來說,服務(wù)器將產(chǎn)生包含以下內(nèi)容的AOF文件:


          *2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n?*3\r\n$3\r\nSET\r\n$3\r\nmsg\r\n$5\r\nhello\r\n?*5\r\n$4\r\nSADD\r\n$6\r\nfruits\r\n$5\r\napple\r\n$6\r\nbanana\r\n$6\r\ncherry\r\n?*5\r\n$5\r\nRPUSH\r\n$7\r\nnumbers\r\n$3\r\n128\r\n$3\r\n256\r\n$3\r\n512\r\n


          在這個AOF文件里面,除了用于指定數(shù)據(jù)庫的SELECT命令是服務(wù)器自動添加的之外,其他都是我們之前通過客戶端發(fā)送的命令。服務(wù)器在啟動時,可以通過載入和執(zhí)行AOF文件中保存的命令來還原服務(wù)器關(guān)閉之前的數(shù)據(jù)庫狀態(tài),以下就是服務(wù)器載入AOF文件并還原數(shù)據(jù)庫狀態(tài)時打印的日志:


          [8321] 05 Sep 11:58:50.448 # Server started, Redisversion 2.9.11[8321] 05 Sep 11:58:50.449 * DB loaded from append only file: 0.000 seconds[8321]?05?Sep?11:58:50.449?*?The?server?is?now?ready?to?accept?connections?on?port?6379


          AOF持久化流程

          AOF持久化功能的實現(xiàn)可以分為命令追加(append)、文件寫入、文件同步(sync)三個步驟。
          命令追加
          當(dāng)AOF持久化功能處于打開狀態(tài)時,服務(wù)器在執(zhí)行完一個寫命令之后,會以協(xié)議格式將被執(zhí)行的寫命令追加到服務(wù)器狀態(tài)的aof_buf緩沖區(qū)的末尾
          文件的寫入與同步
          Redis的服務(wù)器進(jìn)程就是一個事件循環(huán)(loop),這個循環(huán)中的文件事件負(fù)責(zé)接收客戶端的命令請求,以及向客戶端發(fā)送命令回復(fù),而時間事件則負(fù)責(zé)執(zhí)行像serverCron函數(shù)這樣需要定時運行的函數(shù)。
          因為服務(wù)器在處理文件事件時可能會執(zhí)行寫命令,使得一些內(nèi)容被追加到aof_buf緩沖區(qū)里面,所以在服務(wù)器每次結(jié)束一個事件循環(huán)之前,它都會調(diào)用flushAppendOnlyFile函數(shù),考慮是否需要將aof_buf緩沖區(qū)中的內(nèi)容寫入和保存到AOF文件里面,這個過程可以用以下偽代碼表示:


          def eventLoop():      while True:            #  處理文件事件,接收命令請求以及發(fā)送命令回復(fù)             #  處理命令請求時可能會有新內(nèi)容被追加到 aof_buf  緩沖區(qū)中    processFileEvents()              #  處理時間事件         processTimeEvents()              #  考慮是否要將 aof_buf  中的內(nèi)容寫入和保存到 AOF  文件里面               flushAppendOnlyFile()


          flushAppendOnlyFile函數(shù)的行為由服務(wù)器配置的appendfsync選項的值來決定,各個不同值產(chǎn)生的行為如下表所示:

          appendfsync?選項的值flushAppendOnlyFile?函數(shù)的行為
          always將?aof_buf?緩沖區(qū)中的所有內(nèi)容寫入并同步到 AOF 文件。
          everysec將?aof_buf?緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 如果上次同步 AOF 文件的時間距離現(xiàn)在超過一秒鐘, 那么再次對 AOF 文件進(jìn)行同步, 并且這個同步操作是由一個線程專門負(fù)責(zé)執(zhí)行的。
          no將?aof_buf?緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 但并不對 AOF 文件進(jìn)行同步, 何時同步由操作系統(tǒng)來決定。

          如果用戶沒有主動為appendfsync選項設(shè)置值,那么appendfsync選項的默認(rèn)值為everysec


          AOF存在的問題

          為了提高文件的寫入效率, 在現(xiàn)代操作系統(tǒng)中, 當(dāng)用戶調(diào)用?write?函數(shù), 將一些數(shù)據(jù)寫入到文件的時候, 操作系統(tǒng)通常會將寫入數(shù)據(jù)暫時保存在一個內(nèi)存緩沖區(qū)里面, 等到緩沖區(qū)的空間被填滿、或者超過了指定的時限之后, 才真正地將緩沖區(qū)中的數(shù)據(jù)寫入到磁盤里面。
          這種做法雖然提高了效率, 但也為寫入數(shù)據(jù)帶來了安全問題, 因為如果計算機發(fā)生停機, 那么保存在內(nèi)存緩沖區(qū)里面的寫入數(shù)據(jù)將會丟失。
          為此, 系統(tǒng)提供了?fsync?和?fdatasync?兩個同步函數(shù), 它們可以強制讓操作系統(tǒng)立即將緩沖區(qū)中的數(shù)據(jù)寫入到硬盤里面, 從而確保寫入數(shù)據(jù)的安全性。

          AOF 持久化的效率和安全性

          服務(wù)器配置?appendfsync?選項的值直接決定 AOF 持久化功能的效率和安全性。
          當(dāng)?appendfsync?的值為?always?時, 服務(wù)器在每個事件循環(huán)都要將?aof_buf?緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 并且同步 AOF 文件, 所以?always?的效率是?appendfsync?選項三個值當(dāng)中最慢的一個, 但從安全性來說,?always?也是最安全的, 因為即使出現(xiàn)故障停機, AOF 持久化也只會丟失一個事件循環(huán)中所產(chǎn)生的命令數(shù)據(jù)。
          當(dāng)?appendfsync?的值為?everysec?時, 服務(wù)器在每個事件循環(huán)都要將?aof_buf?緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 并且每隔超過一秒就要在子線程中對 AOF 文件進(jìn)行一次同步:從效率上來講,?everysec?模式足夠快, 并且就算出現(xiàn)故障停機, 數(shù)據(jù)庫也只丟失一秒鐘的命令數(shù)據(jù)。
          當(dāng)?appendfsync?的值為?no?時, 服務(wù)器在每個事件循環(huán)都要將?aof_buf?緩沖區(qū)中的所有內(nèi)容寫入到 AOF 文件, 至于何時對 AOF 文件進(jìn)行同步, 則由操作系統(tǒng)控制。
          因為處于?no?模式下的?flushAppendOnlyFile?調(diào)用無須執(zhí)行同步操作, 所以該模式下的 AOF 文件寫入速度總是最快的, 不過因為這種模式會在系統(tǒng)緩存中積累一段時間的寫入數(shù)據(jù), 所以該模式的單次同步時長通常是三種模式中時間最長的:從平攤操作的角度來看,?no?模式和?everysec?模式的效率類似, 當(dāng)出現(xiàn)故障停機時, 使用?no?模式的服務(wù)器將丟失上次同步 AOF 文件之后的所有寫命令數(shù)據(jù)。

          AOF重寫

          AOF持久化是通過保存被執(zhí)行的寫命令來記錄數(shù)據(jù)庫狀態(tài)的,所以隨著服務(wù)器運行時間的流逝,AOF文件中的內(nèi)容會越來越多,文件的體積也會越來越大,如果不加以控制的話,體積過大的AOF文件很可能對Redis服務(wù)器、甚至整個宿主計算機造成影響,并且AOF文件的體積越大,使用AOF文件來進(jìn)行數(shù)據(jù)還原所需的時間就越多。
          為了解決AOF文件體積膨脹的問題,Redis提供了AOF文件重寫(rewrite)功能。通過該功能,Redis服務(wù)器可以創(chuàng)建一個新的AOF文件來替代現(xiàn)有的AOF文件,新舊兩個AOF文件所保存的數(shù)據(jù)庫狀態(tài)相同,但新AOF文件不會包含任何浪費空間的冗余命令,所以新AOF文件的體積通常會比舊AOF文件的體積要小得多。
          雖然Redis將生成新AOF文件替換舊AOF文件的功能命名為“AOF文件重寫”,但實際上,AOF文件重寫并不需要對現(xiàn)有的AOF文件進(jìn)行任何讀取、分析或者寫入操作,這個功能是通過讀取服務(wù)器當(dāng)前的數(shù)據(jù)庫狀態(tài)來實現(xiàn)的。
          在實際中,為了避免在執(zhí)行命令時造成客戶端輸入緩沖區(qū)溢出,重寫程序在處理列表、哈希表、集合、有序集合這四種可能會帶有多個元素的鍵時,會先檢查鍵所包含的元素數(shù)量,如果元素的數(shù)量超過了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值,那么重寫程序?qū)⑹褂枚鄺l命令來記錄鍵的值,而不單單使用一條命令。重寫可以交給子線程。

          全棧架構(gòu)社區(qū)交流群

          ?「全棧架構(gòu)社區(qū)」建立了讀者架構(gòu)師交流群,大家可以添加小編微信進(jìn)行加群。歡迎有想法、樂于分享的朋友們一起交流學(xué)習(xí)。


          掃描添加好友邀你進(jìn)架構(gòu)師群,加我時注明姓名+公司+職位】


          看完本文有收獲?請轉(zhuǎn)發(fā)分享給更多人


          往期資源:
          Flutter 移動應(yīng)用開發(fā)實戰(zhàn) 視頻(開發(fā)你自己的抖音APP)
          Java面試進(jìn)階訓(xùn)練營 第2季(分布式篇)
          Java高級 - 分布式系統(tǒng)開發(fā)技術(shù)視頻


          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  小黄片视频免费观看 | 激情综合五月丁香 | 天天躁日日躁人妻久久澡 | 国产无码久久久久 | 色婷婷之 |