1. 程式人生 > >深入Redis持久化

深入Redis持久化

一、Redis高可用概述

在介紹Redis高可用之前,先說明一下在Redis的語境中高可用的含義。

我們知道,在web伺服器中,高可用是指伺服器可以正常訪問的時間,衡量的標準是在多長時間內可以提供正常服務(99.9%、99.99%、99.999% 等等)。但是在Redis語境中,高可用的含義似乎要寬泛一些,除了保證提供正常服務(如主從分離、快速容災技術),還需要考慮資料容量的擴充套件、資料安全不會丟失等。

在Redis中,實現高可用的技術主要包括持久化、複製、哨兵和叢集,下面分別說明它們的作用,以及解決了什麼樣的問題。

  1. 持久化:持久化是最簡單的高可用方法(有時甚至不被歸為高可用的手段),主要作用是資料備份,即將資料儲存在硬碟,保證資料不會因程序退出而丟失。

  2. 複製:複製是高可用Redis的基礎,哨兵和叢集都是在複製基礎上實現高可用的。複製主要實現了資料的多機備份,以及對於讀操作的負載均衡和簡單的故障恢復。缺陷:故障恢復無法自動化;寫操作無法負載均衡;儲存能力受到單機的限制。

  3. 哨兵:在複製的基礎上,哨兵實現了自動化的故障恢復。缺陷:寫操作無法負載均衡;儲存能力受到單機的限制。

  4. 叢集:通過叢集,Redis解決了寫操作無法負載均衡,以及儲存能力受到單機限制的問題,實現了較為完善的高可用方案。

二、Redis持久化概述

持久化的功能:Redis是記憶體資料庫,資料都是儲存在記憶體中,為了避免程序退出導致資料的永久丟失,需要定期將Redis中的資料以某種形式(資料或命令)從記憶體儲存到硬碟;當下次Redis重啟時,利用持久化檔案實現資料恢復。除此之外,為了進行災難備份,可以將持久化檔案拷貝到一個遠端位置。

Redis持久化分為RDB持久化和AOF持久化:前者將當前資料儲存到硬碟,後者則是將每次執行的寫命令儲存到硬碟(類似於MySQL的binlog);由於AOF持久化的實時性更好,即當程序意外退出時丟失的資料更少,因此AOF是目前主流的持久化方式,不過RDB持久化仍然有其用武之地。

下面依次介紹RDB持久化和AOF持久化;由於Redis各個版本之間存在差異,如無特殊說明,以Redis3.0為準。

三、RDB持久化

RDB持久化是將當前程序中的資料生成快照儲存到硬碟(因此也稱作快照持久化),儲存的檔案字尾是rdb;當Redis重新啟動時,可以讀取快照檔案恢復資料。

1. 觸發條件

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

1) 手動觸發

save命令和bgsave命令都可以生成RDB檔案。

save命令會阻塞Redis伺服器程序,直到RDB檔案建立完畢為止,在Redis伺服器阻塞期間,伺服器不能處理任何命令請求。

而bgsave命令會建立一個子程序,由子程序來負責建立RDB檔案,父程序(即Redis主程序)則繼續處理請求。

此時伺服器執行日誌如下:

bgsave命令執行過程中,只有fork子程序時會阻塞伺服器,而對於save命令,整個過程都會阻塞伺服器,因此save已基本被廢棄,線上環境要杜絕save的使用;後文中也將只介紹bgsave命令。此外,在自動觸發RDB持久化時,Redis也會選擇bgsave而不是save來進行持久化;下面介紹自動觸發RDB持久化的條件。

在此我向大家推薦一個架構學習交流群。交流學習群號874811168 目前受益良多

    2) 自動觸發

    save m n

    自動觸發最常見的情況是在配置檔案中通過save m n,指定當m秒內發生n次變化時,會觸發bgsave。

    例如,檢視redis的預設配置檔案(Linux下為redis根目錄下的redis.conf),可以看到如下配置資訊:

    其中save 900 1的含義是:當時間到900秒時,如果redis資料發生了至少1次變化,則執行bgsave;save 300 10和save 60 10000同理。當三個save條件滿足任意一個時,都會引起bgsave的呼叫。

    save m n的實現原理

    Redis的save m n,是通過serverCron函式、dirty計數器、和lastsave時間戳來實現的。

    serverCron是Redis伺服器的週期性操作函式,預設每隔100ms執行一次;該函式對伺服器的狀態進行維護,其中一項工作就是檢查 save m n 配置的條件是否滿足,如果滿足就執行bgsave。

    dirty計數器是Redis伺服器維持的一個狀態,記錄了上一次執行bgsave/save命令後,伺服器狀態進行了多少次修改(包括增刪改);而當save/bgsave執行完成後,會將dirty重新置為0。

    例如,如果Redis執行了set mykey helloworld,則dirty值會+1;如果執行了sadd myset v1 v2 v3,則dirty值會+3;注意dirty記錄的是伺服器進行了多少次修改,而不是客戶端執行了多少修改資料的命令。

    lastsave時間戳也是Redis伺服器維持的一個狀態,記錄的是上一次成功執行save/bgsave的時間。

    save m n的原理如下:每隔100ms,執行serverCron函式;在serverCron函式中,遍歷save m n配置的儲存條件,只要有一個條件滿足,就進行bgsave。對於每一個save m n條件,只有下面兩條同時滿足時才算滿足:

    (1)當前時間-lastsave > m

    (2)dirty >= n

    save m n 執行日誌

    下圖是save m n觸發bgsave執行時,伺服器列印日誌的情況:

    其他自動觸發機制

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

    • 在主從複製場景下,如果從節點執行全量複製操作,則主節點會執行bgsave命令,並將rdb檔案傳送給從節點

    • 執行shutdown命令時,自動執行rdb持久化,如下圖所示:

    2. 執行流程

    前面介紹了觸發bgsave的條件,下面將說明bgsave命令的執行流程,如下圖所示(圖片來源:https://blog.csdn.net/a1007720052/article/details/79126253):

    圖片中的5個步驟所進行的操作如下:

    1)  Redis父程序首先判斷:當前是否在執行save,或bgsave/bgrewriteaof(後面會詳細介紹該命令)的子程序,如果在執行則bgsave命令直接返回。bgsave/bgrewriteaof 的子程序不能同時執行,主要是基於效能方面的考慮:兩個併發的子程序同時執行大量的磁碟寫操作,可能引起嚴重的效能問題。

    2)  父程序執行fork操作建立子程序,這個過程中父程序是阻塞的,Redis不能執行來自客戶端的任何命令

    3)  父程序fork後,bgsave命令返回”Background saving started”資訊並不再阻塞父程序,並可以響應其他命令

    4)  子程序建立RDB檔案,根據父程序記憶體快照生成臨時快照檔案,完成後對原有檔案進行原子替換

    5)  子程序傳送訊號給父程序表示完成,父程序更新統計資訊

    3. RDB檔案

    RDB檔案是經過壓縮的二進位制檔案,下面介紹關於RDB檔案的一些細節。

    儲存路徑

    RDB檔案的儲存路徑既可以在啟動前配置,也可以通過命令動態設定。

    配置:dir配置指定目錄,dbfilename指定檔名。預設是Redis根目錄下的dump.rdb檔案。

    動態設定:Redis啟動後也可以動態修改RDB儲存路徑,在磁碟損害或空間不足時非常有用;執行命令為config set dir {newdir}和config set dbfilename {newFileName}。如下所示(Windows環境):

    RDB檔案格式

    RDB檔案格式如下圖所示(圖片來源:《Redis設計與實現》):

    其中各個欄位的含義說明如下:

    1)  REDIS:常量,儲存著”REDIS”5個字元。

    2)  db_version:RDB檔案的版本號,注意不是Redis的版本號。

    3)  SELECTDB 0 pairs:表示一個完整的資料庫(0號資料庫),同理SELECTDB 3 pairs表示完整的3號資料庫;只有當資料庫中有鍵值對時,RDB檔案中才會有該資料庫的資訊(上圖所示的Redis中只有0號和3號資料庫有鍵值對);如果Redis中所有的資料庫都沒有鍵值對,則這一部分直接省略。其中:SELECTDB是一個常量,代表後面跟著的是資料庫號碼;0和3是資料庫號碼;pairs則儲存了具體的鍵值對資訊,包括key、value值,及其資料型別、內部編碼、過期時間、壓縮資訊等等。

    4)  EOF:常量,標誌RDB檔案正文內容結束。

    5)  check_sum:前面所有內容的校驗和;Redis在載入RBD檔案時,會計算前面的校驗和並與check_sum值比較,判斷檔案是否損壞。

    壓縮

    Redis預設採用LZF演算法對RDB檔案進行壓縮。雖然壓縮耗時,但是可以大大減小RDB檔案的體積,因此壓縮預設開啟;可以通過命令關閉:

    需要注意的是,RDB檔案的壓縮並不是針對整個檔案進行的,而是對資料庫中的字串進行的,且只有在字串達到一定長度(20位元組)時才會進行。

    4. 啟動時載入

    RDB檔案的載入工作是在伺服器啟動時自動執行的,並沒有專門的命令。但是由於AOF的優先順序更高,因此當AOF開啟時,Redis會優先載入AOF檔案來恢復資料;只有當AOF關閉時,才會在Redis伺服器啟動時檢測RDB檔案,並自動載入。伺服器載入RDB檔案期間處於阻塞狀態,直到載入完成為止。

    Redis啟動日誌中可以看到自動載入的執行:

    Redis載入RDB檔案時,會對RDB檔案進行校驗,如果檔案損壞,則日誌中會列印錯誤,Redis啟動失敗。

    5. RDB常用配置總結

    下面是RDB常用的配置項,以及預設值;前面介紹過的這裡不再詳細介紹。

    • save m n:bgsave自動觸發的條件;如果沒有save m n配置,相當於自動的RDB持久化關閉,不過此時仍可以通過其他方式觸發

    • stop-writes-on-bgsave-error yes:當bgsave出現錯誤時,Redis是否停止執行寫命令;設定為yes,則當硬碟出現問題時,可以及時發現,避免資料的大量丟失;設定為no,則Redis無視bgsave的錯誤繼續執行寫命令,當對Redis伺服器的系統(尤其是硬碟)使用了監控時,該選項考慮設定為no

    • rdbcompression yes:是否開啟RDB檔案壓縮

    • rdbchecksum yes:是否開啟RDB檔案的校驗,在寫入檔案和讀取檔案時都起作用;關閉checksum在寫入檔案和啟動檔案時大約能帶來10%的效能提升,但是資料損壞時無法發現

    • dbfilename dump.rdb:RDB檔名

    • dir ./:RDB檔案和AOF檔案所在目錄

    四、AOF持久化

    RDB持久化是將程序資料寫入檔案,而AOF持久化(即Append Only File持久化),則是將Redis執行的每次寫命令記錄到單獨的日誌檔案中(有點像MySQL的binlog);當Redis重啟時再次執行AOF檔案中的命令來恢復資料。

    與RDB相比,AOF的實時性更好,因此已成為主流的持久化方案。

    1. 開啟AOF

    Redis伺服器預設開啟RDB,關閉AOF;要開啟AOF,需要在配置檔案中配置:

    appendonly yes

    2. 執行流程

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

    AOF的執行流程包括:

    • 命令追加(append):將Redis的寫命令追加到緩衝區aof_buf;

    • 檔案寫入(write)和檔案同步(sync):根據不同的同步策略將aof_buf中的內容同步到硬碟;

    • 檔案重寫(rewrite):定期重寫AOF檔案,達到壓縮的目的。

    1) 命令追加(append)

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

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

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

    Redis提供了多種AOF快取區的同步檔案策略,策略涉及到作業系統的write函式和fsync函式,說明如下:

    為了提高檔案寫入效率,在現代作業系統中,當用戶呼叫write函式將資料寫入檔案時,作業系統通常會將資料暫存到一個記憶體緩衝區裡,當緩衝區被填滿或超過了指定時限後,才真正將緩衝區的資料寫入到硬盤裡。這樣的操作雖然提高了效率,但也帶來了安全問題:如果計算機停機,記憶體緩衝區中的資料會丟失;因此係統同時提供了fsync、fdatasync等同步函式,可以強制作業系統立刻將緩衝區中的資料寫入到硬盤裡,從而確保資料的安全性。

     

    AOF快取區的同步檔案策略由引數appendfsync控制,各個值的含義如下:

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

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

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

    3) 檔案重寫(rewrite)

    隨著時間流逝,Redis伺服器執行的寫命令越來越多,AOF檔案也會越來越大;過大的AOF檔案不僅會影響伺服器的正常執行,也會導致資料恢復需要的時間過長。

    檔案重寫是指定期重寫AOF檔案,減小AOF檔案的體積。需要注意的是,AOF重寫是把Redis程序內的資料轉化為寫命令,同步到新的AOF檔案;不會對舊的AOF檔案進行任何讀取、寫入操作!

    關於檔案重寫需要注意的另一點是:對於AOF持久化來說,檔案重寫雖然是強烈推薦的,但並不是必須的;即使沒有檔案重寫,資料也可以被持久化並在Redis啟動的時候匯入;因此在一些實現中,會關閉自動的檔案重寫,然後通過定時任務在每天的某一時刻定時執行。

    在此我向大家推薦一個架構學習交流群。交流學習群號874811168 目前受益良多


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

    • 過期的資料不再寫入檔案

    • 無效的命令不再寫入檔案:如有些資料被重複設值(set mykey v1, set mykey v2)、有些資料被刪除了(sadd myset v1, del myset)等等

    • 多條命令可以合併為一個:如sadd myset v1, sadd myset v2, sadd myset v3可以合併為sadd myset v1 v2 v3。不過為了防止單條命令過大造成客戶端緩衝區溢位,對於list、set、hash、zset型別的key,並不一定只使用一條命令;而是以某個常量為界將命令拆分為多條。這個常量在redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD中定義,不可更改,3.0版本中值是64。

    通過上述內容可以看出,由於重寫後AOF執行的命令減少了,檔案重寫既可以減少檔案佔用的空間,也可以加快恢復速度。

    檔案重寫的觸發

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

    手動觸發:直接呼叫bgrewriteaof命令,該命令的執行與bgsave有些類似:都是fork子程序進行具體的工作,且都只有在fork時阻塞。

    相關推薦

    深入Redis持久化

    一、Redis高可用概述 在介紹Redis高可用之前,先說明一下在Redis的語境中高可用的含義。 我們知道,在web伺服器中,高可用是指伺服器可以正常訪問的時間,衡量的標準是在多長時間內可以提供正常服務(99.9%、99.99%、99.999% 等等)。但是在Redis語境中,高可用的含義似乎要寬泛

    深入Redis的RDB和AOF兩種持久化方式以及AOF重寫機制的分析

    快取伺服器有一個很重要的指標就是能否持久化,如果快取伺服器不支援持久化的話,一些相對重要的資料都不能存在快取伺服器中了,畢竟誰也不能保證服務百分百可用,一旦快取伺服器宕機,所有資料就都丟失了。 今天來分享一下Redis的持久化兩種持久化方式RDB和AOF。

    Redis持久化深入理解

    用過Redis的都知道,Redis有兩種持久化方式:RDB和AOF,他們的區別大家應該都清楚,所以今天主要想分享一下這兩種持久化方式的底層原理以及實現。 如果讓你手寫一個持久化(架構級)的功能,你沒有思路的話,那希望這個文章可以給你靈感。 1. RDB持久化 1.1 建立 簡單回顧下RDB檔案的建

    Redis持久化的幾種方式——深入解析RDB

    Redis 的讀寫都是在記憶體中,所以它的效能較高,但在記憶體中的資料會隨著伺服器的重啟而丟失,為了保證資料不丟失,我們需要將記憶體中的資料儲存到磁碟,以便 Redis 重啟時能夠從磁碟中恢復原有的資料,而整個過程就叫做 Redis 持久化。 Redis 持久化也是 Redis 和 Memcached

    redis持久化和復制原理

    redisRedis提供了兩種不同的持久化方式: RDB:在指定的時間間隔內生成數據快照,以二進制進行存儲 AOF:記錄服務器執行的所有寫操作命令,並在服務器啟動時,通過重新執行這些命令來還原數據集新命令會被追加到文件的末尾,每隔一段時間在後臺對AOF文件進行重寫使AOF文件的體積不會超出保存數據所需實際大小

    redis持久化

    文件名 當前 onf don set for 內容 不能 span redis支持兩種持久化的方式,可以單獨使用或者結合起來使用 第一種:RDB方式(redis默認的持久化方式) 第二種:AOF方式 一、RDB rdb方式的持久化是通過

    redis持久化之 aof日誌

    bsp img png 常用 使用 app 日誌 back 現在 aof就是把執行的命令寫到文本文件裏面 aof使用過程 第一步: 修改配置文件,並啟動server 第二步, 當前目錄下面會生成一個 appendonly。aof文件,但是是空的     去

    Redis 持久化,寫入磁盤的方式

    磁盤空間 後來 放棄 software gre cat wap adding redis設計 Redis是一個支持持久化的內存數據庫=>也就是說redis需要經常將內存中的數據同步到磁盤來保證持久化。 redis支持四種持久化方式, 一是 Snapshotting(快

    redis 持久化 AOF RDB

    redis aof rdb Redis的AOF持久化策略是將發送到redis服務端的每一條命令都記錄下來,並且保存到硬盤中的AOF文件中,類似打日誌文件,來一條命令就記錄一條。AOF設置AOF文件的位置和RDB文件的位置相同,都是通過dir參數設置,默認的文件名是appendonly.aof,可以

    細說Redis持久化機制

    pac 文件太大 rdb redis持久化 三種方式 server tracking 場景 自己的 概述 Redis不僅能夠作為緩存來使用,也能夠作為內存數據庫。Redis作為內存數據庫使用時。必需要解決一個問題:數據的持久性。有些將Redis作為緩存使用的場

    解密Redis持久化

    div 緩沖區 什麽是 conf 描述 redis主從 啟動 dem 希望 本文內容來源於Redis作者博文,Redis作者說,他看到的所有針對Redis的討論中,對Redis持久化的誤解是最大的,於是他寫了一篇長文來對Redis的持久化進行了系統性的論述。文章非常長,也很

    redis 持久化的兩種方式

    itl note 註定 line end 技術分享 大於等於 默認 更改 一:快照模式   或許在用Redis之初的時候,就聽說過redis有兩種持久化模式,第一種是SNAPSHOTTING模式,還是一種是AOF模式,而且在實戰場景下用的最多的 莫過於SNAPSHO

    redis——持久化

    全部 模式 滿足 ont 執行 get 記錄 進行 logs http://www.cnblogs.com/dengtr/p/5085287.html 眾所周知,redis是內存數據庫,它把數據存儲在內存中,這樣在加快讀取速度的同時也對數據安全性產生了新的問題,即當red

    Redis持久化磁盤IO方式及其帶來的問題   有Redis線上運維經驗的人會發現Redis在物理內存使用比較多,但還沒有超過實際物理內存總容量時就會發生不穩定甚至崩潰的問題,有人認為是基於快照方式持

    發出 != hot server 磁盤io loaddata set 自動 選擇 轉自:http://blog.csdn.net/kaosini/article/details/9176961 一、對Redis持久化的探討與理解 redis是一個支持持久化的內存數據庫

    Redis持久化方式

    很好 conf 一個 文件名 重新 sna 條件 有一個 一次 Snapsotting(快照)方式 snapsotting是默認方式,(把數據做一個備份,將數據存儲在文件) 這種方式將內存中數據照快照方式寫到二進制文件中.默認的文件名為“dump.rd

    redis 持久化存儲之aof和設置密碼

    redis 設置密碼 redis aofRedis 進入Redis設置密碼redis 127.0.0.1:6379[1]> config set requirepass my_redis OK [root@jcsjzx2017 ~]# redis-cli 127.0.0.1:6379> co

    Redis持久化存儲

    情況 slave 臨時 命令 決定 ever 出錯 建議 lena Redis是一個支持持久化的內存數據庫,也就是說redis需要經常將內存中的數據同步到磁盤來保證持久化。redis支持四種持久化方式,一是 Snapshotting(快照)也是默認方式;二是Append

    Redis持久化方式RDB與AOF詳解

    redis持久化 rdb aof 優勢 管理參數 前言Redis提供了兩種數據存儲方式,分別是:cache-only && persistence;cache-only顧名知義,是用與緩存服務的,數據在服務器終止後將消失,在此模式下將不存在"數據恢復"的方式,是一種安全性低

    redis學習(四)redis持久化之RDB、AOF

    出現 add 停用 nbsp 滿足 相同 客戶 -a 工具 redis是內存數據庫,它把數據存儲在內存中,這樣在加快讀取速度的同時也對數據安全性產生了新的問題,即當redis所在服務器發生宕機後,redis數據庫裏的所有數據將會全部丟失。為了解決這個問題,redis提供了持

    redis 持久化

    修改 目錄 文本文 style 兼容性 name 兼容 頻繁 con 一、什麽是持久化 二、常見的持久化方式 三、redis 的持久化方式 rdb快照持久化 (snapshoting) aof( append only file)   (1) redis -之r