<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      redis-持久化

      redis 數據持久化

      作者:w08e

      數據持久化三連問

      redis 宕機數據會丟失嗎

      回答話術

      先說結論,如果我們沒開啟任何持久化機制,那么會丟失全部數據,否則只會丟失部分數據,丟失數據的多少取決于持久化配置。Redis 提供了兩套持久化機制,RDB 快照和 AOF 日志文件追加。

      RDB 它會根據情況定期的 Fork 出一個子進程,生成當前數據庫的全量快照。對于 RDB 快照,假如我們在 RDB 快照生成后宕機,那么會丟失快照生成期間全部增量數據,如果在連快照都沒成功生成,那么就會丟掉全部數據

      image.png

      另一個是 AOF,它通過向 AOF 日志文件追加每一條執行過的指令實現。而當我們僅開啟了 AOF 時,丟失數據的多少取決于我們設置的刷盤策略:當設置為每條指令執行后都刷盤 Always,我們最多丟失一條指令;當設置為每秒刷一次盤的 Eversec 時,最多丟失一秒內的數據;當設置為非主動刷盤的 No 時,則可能丟失上次刷盤后到現在的全部數據。

      image.png

      考慮到兩種模式各有優缺點,沒有一個適中的解決方案,為此,Redis 在 4.0 以后允許通過 aof‐use‐rdb‐preamble 配置開啟混合持久化。

      在開啟混合持久化模式時,AOF 重寫過程中,Redis 會將持久化數據以 RDB 格式寫入 AOF 文件的開頭,隨后將后續的數據以 AOF 格式追加到文件末尾。恢復數據時,Redis 首先加載 RDB 數據,然后加載 AOF 增量數據。

      image.png

      問題詳解

      1. RDB

      RDB 是 Redis 提供的持久化機制之一,它通過將內存中的數據保存到磁盤中的二進制文件來實現。

      我們可以通過 SAVEBGSAVE 指令主動觸發快照的生成,也可以通過配置文件中的 save 配置快照的自動生成條件。

      在現實中出于性能考慮,我們不可能非常頻繁的保存快照,因此要防止數據丟失,最終還是主要依靠 AOF 實現。

      2. AOF

      AOF 是 Redis 提供的另一套持久化機制。當每個寫命令被執行完畢后,它們會被追加寫入 AOF 日志文件的末尾。當 Redis 宕機以后,就可以通過 AOF 日志重放這些命令來恢復數據。

      不過,每次命令執行后,數據會先寫入 AOF 緩存,然后再寫入操作系統緩存,最后才會根據刷盤策略真正的寫入磁盤。因此刷盤策略真正決定了 Redis 宕機時會丟失多少數據:

      • Always:每執行一條指令就刷一次盤,宕機時最多丟失一條指令。
      • Eversec:每秒刷一次盤,宕機時最多丟失一秒內的數據。
      • No:不主動刷盤,由操作系統自己完成,宕機時最多丟失從上一次刷盤到宕機時的全部數據。

      3. 混合持久化

      混合持久化是在 AOF 基礎上的優化措施,嚴格來說還是 AOF,Redis 官方文檔里面持久化方式其實還是只有 AOF 和 RDB 兩種。

      由于 RDB 快照模式會丟失增量數據,AOF 文件較大會影響 Redis 數據恢復的時間,因此 Redis 在 4.0 以后允許通過 aof‐use‐rdb‐preamble 配置開啟混合持久化。

      當 AOF 重寫時,它將會先生成當前時間的 RDB 快照,然后將其寫入新的 AOF 文件頭部位置,接著再把增量數據追加到這個新 AOF 文件中。如此一來,當 Redis 通過 AOF 文件恢復數據時,將會先加載 RDB,然后再重放后半部分的增量數據。這樣就可以大幅度提高數據恢復的速度。

      3.1. 查看混合持久化是否打開

      根據 Redis 版本的不同,有些默認是開啟的,有些默認是關閉狀態,我們可以通過兩種方式開啟混合持久化配置。

      127.0.0.1:6379> config get aof-use-rdb-preamble
      1) "aof-use-rdb-preamble"
      2) "no"
      
      3.2. 通過命令行開啟

      可以通過 config set aof-use-rdb-preamble yes 命令行的方式開啟混合持久化配置,注意開啟后再查一次配置。

      127.0.0.1:6379> config get aof-use-rdb-preamble
      1) "aof-use-rdb-preamble"
      2) "no"
      127.0.0.1:6379> config set aof-use-rdb-preamble yes
      OK
      127.0.0.1:6379> config get aof-use-rdb-preamble
      1) "aof-use-rdb-preamble"
      2) "yes"
      
      3.3. 文件配置開啟

      我們可以在 Redis 的配置文件 redis.conf 中開啟,開啟后確保萬無一失需要再通過 config get aof-use-rdb-preamble 查詢下。

      # Redis can create append-only base files in either RDB or AOF formats. Using
      # the RDB format is always faster and more efficient, and disabling it is only
      # supported for backward compatibility purposes.
      aof-use-rdb-preamble yes
      

      Redis的RDB是怎么實現的?

      img

      回答話術

      當通過 BGSAVE 指令生成 RDB 的時候,Redis 會 fork 出一個子進程,它會基于寫時復制機制,在不阻塞主線程的情況下,將此刻的數據庫全量數據保存為二進制快照。

      具體的來說,在最開始的時候 fork 子進程的時候,操作系統會為其拷貝父進程的內存頁,但是此時兩者都指向同一塊物理內存。當主進程發生寫操作時,會真正的將父進程的數據拷貝到獨立的物理內存中。此時父子進程的物理內存彼此獨立,互不干涉,父進程繼續處理增量數據,而子進程則根據拷貝出來的舊數據生成 RDB 快照。

      image.png

      相對 AOF,RDB 生成的二進制文件更小,數據恢復起來更快,并且整個流程中完全不會阻塞主進程,但是對應的,由于寫時復制,在最壞的情況下可能會占用雙倍內存,并且無法保存增量數據。

      問題詳解

      1. 如何生成 RDB 文件

      我們可以通過 SAVE 命令在主進程中阻塞的生成 RDB 文件,或者通過 BGSAVE 命令指定在子進程中生成 RDB 文件。

      此外,也可以在數據庫中通過 save 選項,指定當在一定的時間范圍內執行了多少次修改時生成 RDB 文件。比如 save 120 10000 表示當在 120 秒內發生了 10000 次修改時,就通過 BGSAVE 在后臺生成一分 RDB 文件。

      2. 實現原理

      當 Redis 在 fork 出一個子進程去生成 RDB 文件時,主進程依然還在不同的接受指令并操作數據。與 AOF 不同,由于 RDB 是快照,因此實際上它不會同步增量數據,不過也不會影響父進程的操作。Redis 通過寫時復制機制實現這樣的效果。

      簡單的來說,當 fork 子進程后,雖然子進程會從父進程中拷貝內存頁,但是實際上的內存頁依然還是指向了原本的物理內存。而當父進程修改了內存后,才會真正在物理內存中復制一遍父進程的數據,并讓子進程的內存頁指向這塊物理內存,這就是寫時復制。

      根據這個原理,當子進程在生成 RDB 文件時,若父進程發生寫操作,由于寫時復制,子進程會得到一份父進程內存頁的拷貝。此時子進程讀取的是此時父進程內存數據的拷貝,而父進程繼續操作他原本的那份內存,兩者互不干涉。

      我們都知道,在 Linux 系統中內存頁一頁是 4KB,由于是以內存頁為單位的復制,所以在這個過程中,只要不是所有內存頁上的數據都發生了修改,那么生成 RDB 文件過程中占用的額外內存是比較低的。

      3. 與 AOF 的區別

      RDB 即 Redis Database,它本質上就是某個時刻的全量數據快照。它以二進制的方式保存了某個時刻 Redis 數據庫中的全部數據,Redis 啟動后只需要將其加載進內存即可恢復數據。

      相比起 AOF,它的優點是:

      • 文件更小:由于 RDB 里面存放的是非常緊湊的二進制數據,因此相比起 AOF 文件,它占用的空間更小,因此也更適合用來頻繁的進行全量備份。
      • 加載更快:Redis 只需要將 RDB 加載進內存即可恢復數據,相比起還需要重放指令的 AOF,它要快得多。
      • 不阻塞主進程:生成 RDB 的過程可以完全在子進程中完成,因而不需要在主線程進行任何 IO 操作。

      對應的,它的缺點是:

      • RDB 需要 fork 出子進程去完成這個任務,當比較頻繁的生成 RDB 文件時,會對 CPU 帶來比較大的壓力;
      • 無法保存增量數據。

      Redis的AOF是怎么實現的?

      回答話術

      AOF 即 Append Only File,它是 Redis 提供的一種持久化機制。

      其原理是每當服務器執行寫指令時,將命令追加到 AOF 日志文件。當 Redis 重新啟動時,他會在本地啟動一個偽客戶端,并按順序重新發送日志中的命令以恢復數據。

      Redis 的 AOF 日志和 MySQL 的 binlog 有點像,當執行一個命令后,數據會先寫入 AOF 緩沖區,再寫入操作系統緩沖區,最后根據刷盤策略調用 fsync 函數將數據刷入磁盤。Redis 默認提供三種刷盤策略:Always(每個命令后都刷盤)、Everysec(每秒刷一次盤)、No(等到操作系統緩沖區滿或定期刷盤)。

      image.png

      當 AOF 日志越來越大的時候,會觸發 AOF 重寫。舉個例子,假如在 Redis 中對 1 遞增了 99 次,那么 AOF 文件會記錄一百條命令,但是實際上我們恢復數據的時候只需要一個最終值 100,中間的步驟都是不需要的。基于這個原理,在 Redis 重寫的過程中,它會開啟一個子進程掃描數據庫,并生成一個新的 AOF 文件去替換舊的文件。這個文件將會比原本的文件精簡,并且哪怕這個過程中 Redis 掛了,也不會影響已有的 AOF 文件。

      不過,在子進程進行 AOF 重寫的過程中,由于主進程還在不停的接受新的指令,因此它除了需要寫自己的 AOF 緩沖區外,還需要將其寫到 AOF 重寫緩沖區中,以此實現重寫過程中的增量數據同步。

      問題詳解

      1. 保存哪些命令

      在 AOF 文件中,只會保存寫指令,或者更準確點說,只會保存修改數據的指令。

      比如,我們依次執行了下述指令:

      1. RPUSH list 1 2 3 4
      2. LRANGE list 0 -1
      3. KEYS *
      4. LPUSH list 1

      那么,最終只會保存兩條:

      1. RPUSH list 1 2 3 4
      2. LPUSH list 1

      2. 數據的保存格式

      值得注意的是,在 Redis 中執行的命令并不會原模原樣的保存到 AOF ,而是以一種比較特殊 $[長度] + [指令] 的格式保存。

      比如,我們執行一個簡單的命令 SET name open8gu,那么 AOF 中對應的內容如下:

      *3
      $3
      SET
      $4
      name
      $7
      open8gu
      

      上述命令的含義如下:

      1. *3 表示接下來有 3 個參數;
      2. $3 表示接下來的參數的長度為 3,SET 是命令名稱;
      3. $4 表示下一個參數的長度為 4,name 是 Key 的名稱;
      4. $7 表示下一個參數的長度為 7,open8gu 是要設置的值。

      image.png

      3. 寫日志的時機

      當 Redis 接收到一條指令的時候,它會先執行指令,然后再寫 AOF 日志。

      這個邏輯與我們熟悉的 MySQL 中的 binlog 不同,后者是寫前日志(Write Ahead Log, WAL),即先寫日志再保存數據,而 AOF 日志則是寫后日志,即先保存數據再寫日志。

      這種處理方式的優點是:

      • 可以確保寫入 AOF 日志指令都是沒有錯誤的可執行的指令,避免寫日志時還需要進行額外的語法/類型檢查,或者等出錯后回滾日志。
      • 不因為寫日志而阻塞當前指令的執行。

      不過對應的缺點也很明顯:

      • 如果執行完指令實例突然掛了,那 AOF 日志中就不會記錄這條指令。
      • 由于 Redis 的大多數命令都由單個線程執行,因此可能因為寫日志而阻塞后一條指令的執行。

      4. 日志的刷盤策略

      實際上,將指令數據寫入磁盤的時候,并不是一步完成的:

      1. 當執行了寫指令后,數據首先被寫入 Redis 自己的 AOF 緩沖區;
      2. 隨后,Redis 會調用操作系統的 write 函數,將數據從 AOF 緩沖區寫入操作系統緩沖區;
      3. 最后,再由 Redis 調用 fsync 函數或操作系統自己刷盤,讓內核緩沖區中的數據真正寫入磁盤。

      第三步即我們通常說的“日志刷盤”。在日志真正的刷到磁盤之前,數據仍然僅保存在內存里,此時一旦服務器宕機,數據將會永久性的丟失。因此,何時刷盤是整個持久化流程的關鍵點。

      在 MySQL 中,我們可以通過 binlog_sync 來指定 binlog 的刷盤策略,而在 Redis 中,我們可以通過 appendfsync 配置項指定 AOF 日志的的刷盤策略:

      • AOF_FSYNC_NO :AOF 緩沖區有數據時(即執行一個命令后),調用 write函數寫入操作系統緩沖區,然后操作系統定期(在 Linux 中通常是 30 秒)或緩沖區滿后再自動寫入磁盤。
      • AOF_FSYNC_EVERYSEC :AOF 緩沖區有數據時(即執行一個命令后),調用 write函數寫入操作系統緩沖區,然后每一秒鐘調用一次 fsync 將數據寫入磁盤。
      • AOF_FSYNC_ALWAYS :AOF 緩沖區有數據時(即執行一個命令后),立刻調用 fsync 將數據寫入磁盤。

      image.png

      這三種配置方式各有優劣,它們會很大程度上的影響 Redis 的性能:

      指令 時機 性能 宕機時丟失的數據
      AOF_FSYNC_NO 不主動刷盤,由操作系統自己決定刷盤時機 所有未寫入磁盤的數據
      AOF_FSYNC_EVERYSEC 每秒保存一次 一秒內的數據
      AOF_FSYNC_ALWAYS 每個命令執行后保存一次 一條指令的數據

      總的來說,核心問題在于如何取舍可靠性與性能

      • 如果你的系統對數據可靠性要求極高,不允許數據丟失,那么你應該選擇 ALWAYS
      • 如果你的系統更在乎性能,而不在意丟失一些數據,那么你可以選擇 NO
      • 如果你想要在兩者間取得平衡,那么你可以選擇 EVERSEC

      5. AOF 重寫

      5.1. 實現原理

      隨著寫入操作的進行,AOF 文件會變得越來越大,而這其中的大多數數據是沒必要保存的。

      比如,你把 1 遞增到 100,那么最終 AOF 會記錄這一過程中的全部 100 條指令。然而實際上我們只需要最終的值 100 即可。

      因此,AOF 提供了一種重寫機制,即當 AOF 文件膨脹到一定程度時,Redis 將直接重新掃描當前數據庫中的數據,然后把它們重寫到一個新 AOF 文件中,并替換舊的 AOF 文件,這個新的 AOF 文件會比原本的文件更小。

      在這個過程中,Redis 實際上完全不會重新讀取原有的 AOF 文件。

      5.2. 觸發條件

      在 2.4 版本以后,當你開啟 AOF 功能,Redis 會在滿足下述三個條件的時候自動觸發 AOF 重寫:

      • 當前沒有正在執行的 AOF 重寫或 RDB 生成操作。
      • 當前的 AOF 文件大于 server.aof_rewrite_min_size 配置。
      • 當前 AOF 的文件大小增幅達到設置的比例(比如比上一次重寫后的文件大了 50%)。

      除此之外,你也可以可以通過 BGREWRITEAOF 命令手動觸發 AOF 重寫。

      5.3. 后臺重寫

      作為一個非常重的 IO 操作,AOF 重寫會長時間的阻塞線程,因此 Reids 會通過操作系統的 fork 函數分離出一個子進程 bgrewriteaof 來完成。

      使用子進程的好處在于:

      • 子進程進行 AOF 重寫時,主進程可以正常執行,避免阻塞。
      • 由于子進程帶有主進程的數據副本,因此不需要像線程通過加鎖控制對數據的訪問。
      5.4. 增量數據的同步

      由于 AOF 重寫基于父子進程,因此也帶來一個問題:當子進程進行 AOF 重寫時,主進程仍然還在接受指令修改數據,因此重寫的 AOF 文件數據與實時數據就可能不一致。

      對此,以 7.0 版本為分界線,Redis 采用了不同的處理方式:

      5.4.1. 7.0 版本之前

      在 7.0 之前,Redis 采用讓主進程同時寫兩份 AOF 文件的方式來處理這個問題。

      簡單的來說,當子進程在進行 AOF 重寫時,如果主進程接受了一個寫指令,那么它在執行后,既要將這個指令追加到 AOF 緩沖區中,也需要將其加入 AOF 重寫緩存中,相當于同時寫兩份文件。

      當子進程完成 AOF 重寫后,它會向父進程發送完成信號,此時父進程將阻塞的將 AOF 重寫緩存區中的數據全部寫入新的 AOF 文件中,然后使用新的 AOF 文件覆蓋舊的 AOF 文件。至此, AOF 重寫就完成了。

      5.4.2. 7.0 版本之后

      在 7.0 之后,當開始 AOF 重寫的時候,主進程直接將增量數據寫到一個全新的增量 AOF 文件中,等到子進程重寫完 AOF,主進程再將增量 AOF 文件與重寫后的 AOF 文件合并,并替換舊的 AOF 文件。

      相比起 7.0 之前,對于同一個增量命令,主進程主需要往增量 AOF 文件里面寫一次即可,不必再向子進程正在重寫的 AOF 文件里面另外再寫一條數據了。

      需要注意的是,雖然我們稱新的 AOF 文件為“增量 AOF”文件,不過對于主進程來說兩個 AOF 文件沒啥區別,只是從某一條命令開始換了一個文件寫罷了,這條命令之前的數據全部在舊 AOF 文件,而這條命令及以后的數據都在新 AOF 文件里,這個過程依然受刷盤策略控制。

      6. 數據的恢復

      當 Redis 重新啟動時,它會創建一個本地的偽客戶端,這個客戶端將會讀取 AOF 日志,并且在還原出命令后發送給 Redis 服務端,直到全部的命令都執行完畢為止。

      另外,根據官網文檔,如果 Redis 在寫 AOF 日志的過程中宕機,或者由于磁盤已滿等不可抗力最終導致 AOF 日志出錯,那么當重啟時,Redis 會丟棄最后一個寫入失敗的指定,或者如果情況更糟糕,則可以通過 redis-check-aof工具嘗試修復它。

      posted @ 2024-08-30 17:16  早點下班回家吃飯叻  閱讀(82)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲第一精品一二三区| 国产日韩综合av在线| 亚洲a∨国产av综合av| 欧美无人区码suv| 粉嫩国产一区二区三区在线| 麻豆成人精品国产免费| 国产一级r片内射免费视频| 人妻无码久久久久久久久久久| 亚洲精品国产免费av| 日韩av一区二区精品不卡| 性欧美欧美巨大69| 久久精品国产99国产精品澳门| 少妇高潮惨叫喷水在线观看| 久久精产国品一二三产品| 国产精品一区 在线播放| 色狠狠一区二区三区香蕉| 日本一级午夜福利免费区| 岛国中文字幕一区二区| 国产91小视频在线观看| 国产精品无码免费播放| 国产综合精品一区二区在线| 艳妇臀荡乳欲伦交换在线播放| 国产成人精品无人区一区| 一区天堂中文最新版在线| 国产一区二区三区AV在线无码观看| 97人妻精品一区二区三区| 九九热精品在线视频免费| 亚洲第一福利网站在线观看| 久久亚洲av成人无码软件| 国产亚洲国产亚洲国产亚洲| 久久久国产精品VA麻豆| 亚洲av产在线精品亚洲第一站| 韩国三级+mp4| 一本本月无码-| 少妇人妻真实偷人精品| AV最新高清无码专区| 97av麻豆蜜桃一区二区| 国产精品亚欧美一区二区三区| 亚洲高清日韩专区精品| 天堂网av成人在线观看| 在线播放亚洲人成电影|