摘要:同時擁有父進程和子進程。當子進程完成對新文件的寫入時,用新文件替換原來的文件,并刪除舊的文件。在保存文件時父進程唯一需要做的就是出一個子進程,接下來的工作全部由子進程來做,父進程不需要再做其他操作,所以持久化方式可以最大化的性能。
一、持久化的作用 1. 什么是持久化
持久化(Persistence),即把數(shù)據(jù)(如內(nèi)存中的對象)保存到可永久保存的存儲設(shè)備中(如磁盤)。
持久化Redis所有數(shù)據(jù)保持在內(nèi)存中,對數(shù)據(jù)的更新將異步地保存到磁盤上。
快照方式持久化就是在某時刻把所有數(shù)據(jù)進行完整備份。
例:Mysql的Dump方式、Redis的RDB方式。
寫日志方式持久化寫日志方式持久化就是把用戶執(zhí)行的所有寫指令(增刪改)備份到文件中,還原數(shù)據(jù)時只需要把備份的所有指令重新執(zhí)行一遍即可。
例:Mysql的Binlog、Redis的AOF、Hbase的HLog。
二、RDB 1. 什么是RDB RDB簡介RDB持久化方式能夠在指定的時間間隔能對你的數(shù)據(jù)進行快照存儲。
在默認情況下, Redis 將數(shù)據(jù)庫快照保存在名字為 dump.rdb的二進制文件中。
在 Redis 運行時, RDB 程序?qū)斍皟?nèi)存中的數(shù)據(jù)庫快照保存到磁盤文件中, 在 Redis 重啟動時, RDB 程序可以通過載入 RDB 文件來還原數(shù)據(jù)庫的狀態(tài)。
當 Redis 需要保存 dump.rdb 文件時, 服務(wù)器執(zhí)行以下操作:
Redis 調(diào)用forks。同時擁有父進程和子進程。
子進程將數(shù)據(jù)集寫入到一個臨時 RDB 文件中。
當子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,并刪除舊的 RDB 文件。
這種工作方式使得 Redis 可以從寫時復(fù)制(copy-on-write)機制中獲益。
2. RDB的三種主要觸發(fā)機制 save命令(同步數(shù)據(jù)到磁盤上)save 命令執(zhí)行一個同步操作,以RDB文件的方式保存所有數(shù)據(jù)的快照。
127.0.0.1:6379> save OK
由于 save 命令是同步命令,會占用Redis的主進程。若Redis數(shù)據(jù)非常多時,save命令執(zhí)行速度會非常慢,阻塞所有客戶端的請求。
因此很少在生產(chǎn)環(huán)境直接使用SAVE 命令,可以使用BGSAVE 命令代替。如果在BGSAVE命令的保存數(shù)據(jù)的子進程發(fā)生錯誤的時,用 SAVE命令保存最新的數(shù)據(jù)是最后的手段。
bgsave 命令執(zhí)行一個異步操作,以RDB文件的方式保存所有數(shù)據(jù)的快照。
127.0.0.1:6379> bgsave Background saving started
Redis使用Linux系統(tǒng)的fock()生成一個子進程來將DB數(shù)據(jù)保存到磁盤,主進程繼續(xù)提供服務(wù)以供客戶端調(diào)用。
如果操作成功,可以通過客戶端命令LASTSAVE來檢查操作結(jié)果。
命令 | save | bgsave |
---|---|---|
IO類型 | 同步 | 異步 |
阻塞? | 是 | 是(阻塞發(fā)生在fock(),通常非??欤?/td> |
復(fù)雜度 | O(n) | O(n) |
優(yōu)點 | 不會消耗額外的內(nèi)存 | 不阻塞客戶端命令 |
缺點 | 阻塞客戶端命令 | 需要fock子進程,消耗內(nèi)存 |
除了手動執(zhí)行 save 和 bgsave 命令實現(xiàn)RDB持久化以外,Redis還提供了自動自動生成RDB的方式。
你可以通過配置文件對 Redis 進行設(shè)置, 讓它在“ N 秒內(nèi)數(shù)據(jù)集至少有 M 個改動”這一條件被滿足時, 自動進行數(shù)據(jù)集保存操作。
比如說, 以下設(shè)置會讓 Redis 在滿足“ 60 秒內(nèi)有至少有 1000 個鍵被改動”這一條件時, 自動進行數(shù)據(jù)集保存操作:
save 60 10003. RDB相關(guān)配置
# RDB自動持久化規(guī)則 # 當 900 秒內(nèi)有至少有 1 個鍵被改動時,自動進行數(shù)據(jù)集保存操作 save 900 1 # 當 300 秒內(nèi)有至少有 10 個鍵被改動時,自動進行數(shù)據(jù)集保存操作 save 300 10 # 當 60 秒內(nèi)有至少有 10000 個鍵被改動時,自動進行數(shù)據(jù)集保存操作 save 60 10000 # RDB持久化文件名 dbfilename dump-4. RDB的優(yōu)點.rdb # 數(shù)據(jù)持久化文件存儲目錄 dir /var/lib/redis # bgsave發(fā)生錯誤時是否停止寫入,通常為yes stop-writes-on-bgsave-error yes # rdb文件是否使用壓縮格式 rdbcompression yes # 是否對rdb文件進行校驗和檢驗,通常為yes rdbchecksum yes
RDB是一個非常緊湊的文件,它保存了某個時間點得數(shù)據(jù)集,非常適用于數(shù)據(jù)集的備份,比如你可以在每個小時報保存一下過去24小時內(nèi)的數(shù)據(jù),同時每天保存過去30天的數(shù)據(jù),這樣即使出了問題你也可以根據(jù)需求恢復(fù)到不同版本的數(shù)據(jù)集。
RDB是一個緊湊的單一文件,很方便傳送到另一個遠端數(shù)據(jù)中心或者亞馬遜的S3(可能加密),非常適用于災(zāi)難恢復(fù)。
RDB在保存RDB文件時父進程唯一需要做的就是fork出一個子進程,接下來的工作全部由子進程來做,父進程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。
與AOF相比,在恢復(fù)大的數(shù)據(jù)集的時候,RDB方式會更快一些。
5. RDB的缺點耗時、耗性能。RDB 需要經(jīng)常fork子進程來保存數(shù)據(jù)集到硬盤上,當數(shù)據(jù)集比較大的時候,fork的過程是非常耗時的,可能會導(dǎo)致Redis在一些毫秒級內(nèi)不能響應(yīng)客戶端的請求。如果數(shù)據(jù)集巨大并且CPU性能不是很好的情況下,這種情況會持續(xù)1秒,AOF也需要fork,但是你可以調(diào)節(jié)重寫日志文件的頻率來提高數(shù)據(jù)集的耐久度。
不可控、丟失數(shù)據(jù)。如果你希望在redis意外停止工作(例如電源中斷)的情況下丟失的數(shù)據(jù)最少的話,那么RDB不適合你。雖然你可以配置不同的save時間點(例如每隔5分鐘并且對數(shù)據(jù)集有100個寫的操作),是Redis要完整的保存整個數(shù)據(jù)集是一個比較繁重的工作,你通常會每隔5分鐘或者更久做一次完整的保存,萬一在Redis意外宕機,你可能會丟失幾分鐘的數(shù)據(jù)。
三、AOF 1. 什么是AOF快照功能(RDB)并不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那么服務(wù)器將丟失最近寫入、且仍未保存到快照中的那些數(shù)據(jù)。 從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化。
你可以在配置文件中打開AOF方式:
appendonly yes
打開AOF后, 每當 Redis 執(zhí)行一個改變數(shù)據(jù)集的命令時(比如 SET), 這個命令就會被追加到 AOF 文件的末尾。這樣的話, 當 Redis 重新啟時, 程序就可以通過重新執(zhí)行 AOF 文件中的命令來達到重建數(shù)據(jù)集的目的。
AOF運行原理 - 創(chuàng)建 AOF運行原理 - 恢復(fù) 2. AOF持久化的三種策略你可以通過配置文件配置 Redis 多久才將數(shù)據(jù) fsync 到磁盤一次。
always每次有新命令追加到 AOF 文件時就執(zhí)行一次 fsync :非常慢,也非常安全。
everysec每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),并且在故障時只會丟失 1 秒鐘的數(shù)據(jù)。
推薦(并且也是默認)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。
從不 fsync :將數(shù)據(jù)交給操作系統(tǒng)來處理,由操作系統(tǒng)來決定什么時候同步數(shù)據(jù)。更快,也更不安全的選擇。
always、everysec、no對比命令 | 優(yōu)點 | 缺點 |
---|---|---|
always | 不丟失數(shù)據(jù) | IO開銷大,一般SATA磁盤只有幾百TPS |
everysec | 每秒進行與fsync,最多丟失1秒數(shù)據(jù) | 可能丟失1秒數(shù)據(jù) |
no | 不用管 | 不可控 |
推薦(并且也是默認)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。
3. AOF重寫因為 AOF 的運作方式是不斷地將命令追加到文件的末尾, 所以隨著寫入命令的不斷增加, AOF 文件的體積也會變得越來越大。舉個例子, 如果你對一個計數(shù)器調(diào)用了 100 次 INCR , 那么僅僅是為了保存這個計數(shù)器的當前值, AOF 文件就需要使用 100 條記錄(entry)。然而在實際上, 只使用一條 SET 命令已經(jīng)足以保存計數(shù)器的當前值了, 其余 99 條記錄實際上都是多余的。
為了處理這種情況, Redis 支持一種有趣的特性: 可以在不打斷服務(wù)客戶端的情況下, 對 AOF 文件進行重建(rebuild)。執(zhí)行 bgrewriteaof 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數(shù)據(jù)集所需的最少命令。
Redis 2.2 需要自己手動執(zhí)行 bgrewriteaof 命令; Redis 2.4 則可以通過配置自動觸發(fā) AOF 重寫。
減少磁盤占用量
加速數(shù)據(jù)恢復(fù)
AOF重寫的實現(xiàn)方式
bgrewriteaof 命令
Redis bgrewriteaof 命令用于異步執(zhí)行一個 AOF(AppendOnly File)文件重寫操作。重寫會創(chuàng)建一個當前AOF文件的體積優(yōu)化版本。
即使 bgrewriteaof 執(zhí)行失敗,也不會有任何數(shù)據(jù)丟失,因為舊的AOF文件在 bgrewriteaof 成功之前不會被修改。
AOF 重寫由 Redis 自行觸發(fā),bgrewriteaof 僅僅用于手動觸發(fā)重寫操作。
具體內(nèi)容:
如果一個子Redis是通過磁盤快照創(chuàng)建的,AOF重寫將會在RDB終止后才開始保存。這種情況下BGREWRITEAOF任然會返回OK狀態(tài)碼。從Redis 2.6起你可以通過INFO命令查看AOF重寫執(zhí)行情況。
如果只在執(zhí)行的AOF重寫返回一個錯誤,AOF重寫將會在稍后一點的時間重新調(diào)用。
AOF重寫配置
配置名 | 含義 |
---|---|
auto-aof-rewrite-min-size | 觸發(fā)AOF文件執(zhí)行重寫的最小尺寸 |
auto-aof-rewrite-percentage | 觸發(fā)AOF文件執(zhí)行重寫的增長率 |
統(tǒng)計名 | 含義 |
---|---|
aof_current_size | AOF文件當前尺寸(字節(jié)) |
aof_base_size | AOF文件上次啟動和重寫時的尺寸(字節(jié)) |
AOF重寫自動觸發(fā)機制,需要同時滿足下面兩個條件:
aof_current_size > auto-aof-rewrite-min-size
(aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage
假設(shè) Redis 的配置項為:
auto-aof-rewrite-min-size 64mb auto-aof-rewrite-percentage 100
當AOF文件的體積大于64Mb,并且AOF文件的體積比上一次重寫之久的體積大了至少一倍(100%)時,Redis將執(zhí)行 bgrewriteaof 命令進行重寫。
AOF重寫的流程 3. AOF相關(guān)配置# 開啟AOF持久化方式 appendonly yes # AOF持久化文件名 appendfilename appendonly-4. AOF的優(yōu)點.aof # 每秒把緩沖區(qū)的數(shù)據(jù)同步到磁盤 appendfsync everysec # 數(shù)據(jù)持久化文件存儲目錄 dir /var/lib/redis # 是否在執(zhí)行重寫時不同步數(shù)據(jù)到AOF文件 # 這里的 yes,就是執(zhí)行重寫時不同步數(shù)據(jù)到AOF文件 no-appendfsync-on-rewrite yes # 觸發(fā)AOF文件執(zhí)行重寫的最小尺寸 auto-aof-rewrite-min-size 64mb # 觸發(fā)AOF文件執(zhí)行重寫的增長率 auto-aof-rewrite-percentage 100
使用AOF 會讓你的Redis更加耐久: 你可以使用不同的fsync策略:無fsync,每秒fsync,每次寫的時候fsync。使用默認的每秒fsync策略,Redis的性能依然很好(fsync是由后臺線程進行處理的,主線程會盡力處理客戶端請求),一旦出現(xiàn)故障,你最多丟失1秒的數(shù)據(jù)。
AOF文件是一個只進行追加的日志文件,所以不需要寫入seek,即使由于某些原因(磁盤空間已滿,寫的過程中宕機等等)未執(zhí)行完整的寫入命令,你也也可使用redis-check-aof工具修復(fù)這些問題。
Redis 可以在 AOF 文件體積變得過大時,自動地在后臺對 AOF 進行重寫: 重寫后的新 AOF 文件包含了恢復(fù)當前數(shù)據(jù)集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在創(chuàng)建新 AOF 文件的過程中,會繼續(xù)將命令追加到現(xiàn)有的 AOF 文件里面,即使重寫過程中發(fā)生停機,現(xiàn)有的 AOF 文件也不會丟失。 而一旦新 AOF 文件創(chuàng)建完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,并開始對新 AOF 文件進行追加操作。
AOF 文件有序地保存了對數(shù)據(jù)庫執(zhí)行的所有寫入操作, 這些寫入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內(nèi)容非常容易被人讀懂, 對文件進行分析(parse)也很輕松。 導(dǎo)出(export) AOF 文件也非常簡單: 舉個例子, 如果你不小心執(zhí)行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那么只要停止服務(wù)器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重啟 Redis , 就可以將數(shù)據(jù)集恢復(fù)到 FLUSHALL 執(zhí)行之前的狀態(tài)。
5. AOF的缺點對于相同的數(shù)據(jù)集來說,AOF 文件的體積通常要大于 RDB 文件的體積。
根據(jù)所使用的 fsync 策略,AOF 的速度可能會慢于 RDB 。 在一般情況下, 每秒 fsync 的性能依然非常高, 而關(guān)閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。
四、RDB和AOF的抉擇 1. RDB 和 AOF 對比- | RDB | AOF |
---|---|---|
啟動優(yōu)先級 | 低 | 高 |
體積 | 小 | 大 |
恢復(fù)速度 | 快 | 慢 |
數(shù)據(jù)安全性 | 丟數(shù)據(jù) | 根據(jù)策略決定 |
一般來說, 如果想達到足以媲美 PostgreSQL 的數(shù)據(jù)安全性, 你應(yīng)該同時使用兩種持久化功能。
如果你非常關(guān)心你的數(shù)據(jù), 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失, 那么你可以只使用 RDB 持久化。
有很多用戶都只使用 AOF 持久化, 但并不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便于進行數(shù)據(jù)庫備份, 并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比 AOF 恢復(fù)的速度要快。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/29279.html
閱讀 2618·2021-09-28 09:36
閱讀 2228·2021-09-07 09:58
閱讀 1492·2019-08-26 13:53
閱讀 1275·2019-08-23 17:53
閱讀 3023·2019-08-23 15:34
閱讀 1850·2019-08-23 15:34
閱讀 2864·2019-08-23 12:04
閱讀 3717·2019-08-23 10:56