首頁  >  文章  >  資料庫  >  一文詳解redis中的高可用與持久化

一文詳解redis中的高可用與持久化

青灯夜游
青灯夜游轉載
2022-02-02 08:00:311933瀏覽

這篇文章帶大家聊聊redis中的高可用與持久化,看看Redis 持久化的功能、兩種方式(RDB和AOF),希望對大家有幫助!

一文詳解redis中的高可用與持久化

一、Redis 高可用

1. Redis 高可用概述

  在web伺服器中,高可用是指伺服器可以正常訪問的時間,衡量的標準是在多長時間內可以提供正常服務(99.9%、99.99%、99.999%等等)。 【相關推薦:Redis影片教學

  但是在Redis語境中,高可用的含義似乎要寬泛一些,除了保證提供正常服務(如主從分離、快速容災技術),還需要考慮資料容量的擴展、資料安全不會遺失等。

2. Redis 高可用策略

在Redis中,實現高可用的技術主要包括持久化、主從分離、哨兵和叢集。

高可用策略 說明
持久化是最簡單的高可用方法(有時甚至不被歸類為高可用的手段),主要作用是資料備份,即將資料儲存在硬碟,保證資料不會因進程退出而遺失。
主從複製######主從複製是高可用Redis的基礎,哨兵和叢集都是在主從複製基礎上實現高可用的。主從複製主要實現了資料的多機備份,以及對於讀取操作的負載平衡和簡單的故障還原。缺陷:故障復原無法自動化,寫入操作無法負載平衡,儲存能力受到單機的限制。 ############哨兵######在主從複製的基礎上,哨兵實現了自動化的故障復原。缺陷:寫入操作無法負載平衡,儲存能力受到單機的限制。 ############集群######透過集群,Redis解決了寫入操作無法負載平衡,以及儲存能力受到單機限制的問題,實現了較為完善的高可用方案。 ############

二、Redis 持久化

1. Redis 持久化的功能

  Redis是記憶體資料庫,資料都是儲存在記憶體中,為了避免伺服器斷電等原因導致Redis進程異常退出後資料的永久遺失,需要定期將Redis中的資料以某種形式(資料或命令)從記憶體保存到硬碟;當下次Redis重啟時,利用持久化檔案實現資料復原。除此之外,為了進行災難備份,可以將持久化文件拷貝到一個遠端位置。

2. Redis 持久化的兩種方式

  • RDB持久化
    原理是將Redis在記憶體中的資料庫記錄定時保存到磁碟上。
  • AOF持久化(append only file)
    原理是將Redis的操作日誌以追加的方式寫入文件,類似於MySQL的binlog。
    由於AOF持久化的即時性較好,即當流程意外退出時遺失的資料較少,因此AOF是目前主流的持久化方式,不過RDB持久化仍有其用武之地。

3. RDB 持久化

  RDB持久化是指在指定的時間間隔內將記憶體中目前進程中的資料產生快照儲存到硬碟(因此也稱為快照持久化),用二進制壓縮存儲,保存的文件後綴是rdb;當Redis重新啟動時,可以讀取快照文件恢復數據。

3.1 觸發條件

RDB持久化的觸發分為手動觸發和自動觸發兩種。

3.1.1 手動觸發

  • save指令和bgsave指令都可以產生RDB檔。
  • save指令會阻塞Redis伺服器程序,直到RDB檔案建立完畢為止,在Redis伺服器阻塞期間,伺服器不能處理任何指令請求。
  • bgsave指令會fork()一個子程序,由子程序來負責建立RDB文件,父行程(即Redis主程序)則繼續處理請求。
  • bgsave指令執行過程中,只有fork子程序時會阻塞伺服器,而對於save指令,整個過程都會阻塞伺服器,因此save已基本被廢棄,線上環境要杜絕save的使用。

3.1.2 自動觸發

  • 在自動觸發RDB持久化時,Redis也會選擇bgsave而不是save來進行持久化。

3.2 設定方式

  • 透過修改設定檔進行設定:save m n
  • #自動觸發最常見的情況是在設定檔中透過save m n,指定當m秒內發生n次變化時,會觸發bgsave。
[root@localhost ~]# vim /etc/redis/6379.conf ##219行,以下三个save条件满足任意一个时,都会引起bgsave的调用save 900 1	##当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsavesave 300 10	##当时间到300秒时,如果redis数据发生了至少10次变化,则执行bgsavesave 60 10000	##当时间到60秒时,如果redis数据发生了至少10000次变化,则执行bgsave##254行,指定RDB文件名dbfilename dump.rdb##264行,指定RDB文件和AOF文件所在目录dir /var/lib/redis/6379##242行,是否开启RDB文件压缩rdbcompression yes

3.3 其他自動觸發機制

除了save m n以外,還有一些其他情況會觸發bgsave:

  • 在主從複製場景下,如果從節點執行全量複製操作,則主節點會執行bgsave命令,並將rdb檔案傳送給從節點。
  • 執行shutdown指令時,自動執行rdb持久化。

3.4 執行流程

一文詳解redis中的高可用與持久化

  • Redis父程式先判斷:目前是否在執行save,或bgsave/bgrewriteaof的子進程,如果在執行則bgsave指令直接回傳。 bgsave/bgrewriteaof的子程序不能同時執行,主要是基於效能方面的考量;兩個並發的子程序同時執行大量的磁碟寫入操作,可能會造成嚴重的效能問題。
  • 父行程執行fork操作建立子程序,這個過程中父行程是阻塞的,Redis不能執行來自客戶端的任何指令。
  • 父進程fork後,bgsave命令返回“Background saving started”訊息並不再阻塞父進程,並且可以響應其他命令
  • 子進程創建RDB文件,根據父進程內存快照生成臨時快照文件,完成後對原始文件進行原子替換
  • 子進程發送信號給父進程表示完成,父進程更新統計信息

3.5 啟動時加載

  RDB檔案的載入工作是在伺服器啟動時自動執行的,並沒有專門的命令。但是由於AOF的優先順序較高,因此當AOF開啟時,Redis會優先載入AOF檔來恢復資料;只有當AOF關閉時,才會在Redis伺服器啟動時偵測RDB文件,並自動載入。伺服器載入RDB檔案期間處於阻塞狀態,直到載入完成為止。
  Redis載入RDB檔案時,會對RDB檔案進行校驗,如果檔案損壞,則日誌中會列印錯誤,Redis啟動失敗。

4. AOF 持久化

  RDB持久化是將進程資料寫入文件,而AOF持久化則是將Redis執行的每次寫、刪除命令記錄到單獨的日誌文件中,查詢操作不會記錄;當Redis重啟時再次執行AOF檔案中的命令來恢復資料。
  與RDB相比,AOF的即時性較好,因此已成為主流的持久化方案。

4.1 開啟AOF

Redis伺服器預設開啟RDB,關閉AOF;要開啟AOF,需要在設定檔中設定

[root@localhost ~]# vim /etc/redis/6379.conf ##700行,修改,开启AOFappendonly yes##704行,指定AOF文件名称appendfilename "appendonly.aof"##796行,是否忽略最后一条可能存在问题的指令aof-load-truncated yes[root@localhost ~]# /etc/init.d/redis_6379 restartStopping ...
Redis stopped
Starting Redis server...

4.2 執行流程

由於需要記錄Redis的每個寫入命令,因此AOF不需要觸發,下面介紹AOF的執行流程。

AOF的執行流程包括:

  • 指令追加(append):將Redis的寫入指令追加到緩衝區aof_buf;
  • 檔案寫入(write)和檔案同步(sync):根據不同的同步策略將aof_buf中的內容同步到硬碟;
  • 檔案重寫(rewrite):定期重寫AOF文件,達到壓縮的目的。

4.2.1 命令追加(append)

Redis先將命令追加到緩衝區,而不​​是直接寫入文件,主要是為了避免每次有寫入命令都直接寫入硬碟,導致硬碟IO稱為Redis負載的瓶頸。

指令追加的格式是Redis指令請求的協定格式,它是一種純文字格式,具有相容性好、可讀性強、容易處理、操作簡單、避免二次開銷等優點。在AOF檔案中,除了用來指定資料庫的select指令(如select 0為選取0號資料庫)是由Redis新增的,其他都是客戶端發送來的寫入指令。

4.2.2 檔案寫入(write)和檔案同步(sync)

Redis提供了多種AOF快取區的同步檔案策略,策略涉及到作業系統的write和fsync函數,說明如下:
為了提高檔案寫入效率,在現代作業系統中,當使用者呼叫write函數將資料寫入檔案時,作業系統通常會將資料暫存到一個記憶體緩衝區裡,當緩衝區被填滿或超過了指定時限後,才真正將緩衝區的資料寫入到硬碟裡。這樣的操作雖然提高了效率,但也帶來了安全性問題:如果電腦停機,記憶體緩衝區中的資料會遺失;因此系統同時提供了fsync、fdatasync等同步函數,可以強製作業系統立刻將緩衝區中的資料寫入到硬碟裡,確保資料的安全性。

4.2.3 三種同步方式

AOF快取區的同步檔案策略有三種同步方式,透過對/etc/redis/6379.conf的729行的修改進行設定。

4.2.3.1 appendfsync always

指令寫入aof_buf後立即呼叫系統fsync操作同步到AOF文件,fsync完成後執行緒回傳。在這種情況下,每次有寫入指令都要同步到AOF文件,硬碟IO成為效能瓶頸,Redis只能支援大約幾百TPS寫入,嚴重降低了Redis的效能;即便是使用固態硬碟(SSD),每秒大約也只能處理幾萬個指令,而且會大幅降低SSD的壽命。

4.2.3.2 appendfsync no

指令寫入aof_buf後呼叫系統write操作,不對AOF檔做fsync同步;同步由作業系統負載,通常同步週期為30秒。在這種情況下,檔案同步的時間不可控,緩衝區中堆積的資料會很多,資料安全性無法保證。

4.2.3.3 appendfsync everysec(建議)

命令寫入aof_buf後呼叫系統write操作,write完成後執行緒傳回:fsync同步檔案操作由專門的執行緒每秒呼叫一次。 everysec是前述兩種策略的折衷方案中,是效能和資料安全性的平衡,一次是Redis的預設配置,也是我們建議的配置。

4.2.4 檔案重寫(rewrite)

隨著時間流逝,Redis伺服器執行的寫入指令越來越多,AOF檔也會越來越大;過大的AOF文件不僅會影響伺服器的正常運行,也會導致資料恢復所需的時間過長。
文件重寫是指定期間重寫AOF文件,減少AOF文件的體積。要注意的是,AOF重寫是把Redis行程內的資料轉換成寫入指令,同步到新的AOF檔;不會對舊的AOF檔進行任何讀取、寫入操作。
關於文件重寫需要注意的另一點是:對於AOF持久化來說,文件重寫雖然是強烈建議的,但並不是必須的;即使沒有文件重寫,數據也可以被持久化並在Redis啟動的時候導入;因此在某些現實中,會關閉自動的文件重寫,然後定時任務在每天的某一時刻定時執行。

4.2.4.1 具有壓縮功能的原因

文件重寫之所以能夠壓縮AOF文件,原因在於:

    ##過期的資料不再寫入文件。
  • 無效的指令不再寫入檔案:如有些資料被重複設定(set mykey v1,set mykey v2)、有些資料被刪除了(set myset v1,del myset)等。
  • 多條指令可以合併為一個:如sadd myset v1,sadd myset v2,sadd myset v3可以合併為sadd myset v1 v2 v3。
透過上述原因可以看出,由於重寫後AOF執行的指令減少了,檔案重寫既可以減少檔案所佔用的空間,也可以加快復原速度。

4.2.4.2 檔案重寫的觸發
檔案重寫分為手動觸發和自動觸發:

  • 手動觸發:直接呼叫bfrewriteaof指令,該指令的執行與bgsave有些類似,都是fork進程進行具體的工作,且都只有在fork時阻塞。
  • 自動觸發:透過設定auto-aof-rewrite-min-size選項和auto-aof-rewrite-percentage選項自動執行bgrewriteaof。只有當auto-aof-rewrite-min-size和auto-aof-rewrite-percentage兩個選項同時滿足時,才會自動觸發AOF重寫,即bgrewriteaof操作。

自動觸發的設定位於/etc/redis/6379.conf的771行和772行

  • auto-aof-rewrite-percentage 100
    當前AOF檔案大小(即aof_current_size)是上次日誌重寫時AOF檔案大小(aof_base_size)兩倍時,發生bgrewriteaof操作
  • auto-aof-rewrite-min-size 64mb
    目前AOF檔執行bgrewriteaof指令的最小值,避免剛開始啟動Redis時由於檔案尺寸較小導致頻繁的bgrewriteaof
4.2.4.3 檔案重寫的流程

一文詳解redis中的高可用與持久化
檔案重寫的流程如下:

  • Redis父程式先平判斷目前是否存在正在執行bgsave/bgrewriteaof的子程式;如果存在則bgrewriteaof指令直接傳回,如果存在bgsave命令則等bgsave執行完成後再執行。
  • 父進程執行fork操作建立子進程,這個過程中父進程是阻塞的。
  • 父進程fork後,bgrewriteaof指令回傳「Background append only file rewrite started」訊息並不再阻塞父行程,並且可以回應其他指令。 Redis的所有寫入指令仍寫入AOF緩衝區,並依照appendfsync策略同步到硬碟,確保原有AOF機制的正確。
  • 由於fork操作使用寫入時複製技術,子程序只能共享fork操作時的記憶體資料。由於父進程仍在回應指令,Redis使用AOF重寫緩衝區(aof_rewrite_buf)保存這部分數據,防止新AOF檔案產生期間遺失這部分資料。也就是說,bgrewriteaof執行期間,Redis的寫指令同時追加到aof_buf和aof_rewrite_buf兩個緩衝區。
  • 子程序根據記憶體快照,依照指令合併規則寫入到新的AOF檔。
  • 子進程寫完新的AOF檔案後,向父進程發出訊號,父進程更新統計訊息,具體可以透過info persistence查看。
  • 父程序把AOF重寫緩衝區的資料寫入到新的AOF文件,這樣就保證了新AOF文件所保存的資料庫狀態和伺服器目前狀態一致。
  • 使用新的AOF檔取代舊文件,文成AOF重寫。

關於檔案重寫的流程,有兩點需要特別注意:

  • 重寫由父程式fork子程式進行
  • 重寫期間Redis執行的寫入指令,需要追加到新的AOF檔中,為此Redis引進例如aof_rewrite_buf快取
##4.3 啟動時載入

    #當AOF開啟時,Redis啟動時會優先載入AOF檔來恢復資料;只有當AOF關閉時,才會載入RDB檔案恢復資料。
  • 當AOF開啟,但AOF檔案不存在時,即使RDB檔案存在也不會載入。
  • Redis載入AOF檔時,會對AOF檔進行校驗,如果檔案損壞,則日誌中會列印錯誤,Redis啟動失敗。但如果是AOF檔結尾不完整(機器突然宕機等容易導致檔案尾部不完整),且aof_load_truncated參數開啟,則日誌中會輸出警告,Redis忽略掉AOF檔的尾部,啟動成功。 aof_load_truncated參數預設是開啟的。
5. RDB 和AOF 的優缺點

RDB持久化

優點:RDB檔案緊湊,體積小,網路傳輸快,適合全量複製;恢復速度比AOF快很多。當然,與AOF相比,RDB最重要的優點之一是對性能的影響相對較小。

缺點:RDB檔案的知名缺點在於其資料快照的持久化方式決定了必然做不到即時持久化,而在資料越來越重要的今天,資料的大量遺失很多時候是無法接受的,因此AOF持久化成為主流。此外,RDB檔案需要滿足特定格式,相容性差(如舊版的Redis不相容新版本的RDB檔案)。
對於RDB持久化,一方面是bgsave在進行fork操作時Redis主程序會阻塞,另一方面,子程序向硬碟寫入資料也會帶來IO壓力。

AOF持久化

與RDB持久化相對應,AOF的優先於支援秒數持久化、相容性好,缺點是檔案大、復原速度慢,對性能影響大。

對於AOF持久化,向硬碟寫入資料的頻率大大提高(everysec策略下為秒級),IO壓力更大,甚至可能在成AOF追加阻塞問題。

AOF檔的重寫與RDB的bgsave類似,會有fork時的阻塞和子程序的IO壓力問題。相對來說,由於AOF向硬碟中寫資料的頻率更高,因此對Redis主流程效能的影響會更大。

一般來說,建議關閉AOF的自動重寫功能,並在重寫操作設定計劃任務,放在凌晨業務量低的時候進行,以降低AOF對主進程性能的影響以及IO的讀寫壓力。

更多程式相關知識,請造訪:程式設計入門! !

以上是一文詳解redis中的高可用與持久化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除