redis(7)、redis持久化
2019獨角獸企業重金招聘Python工程師標準>>>
redis持久化,顧名思義,就是把內存中的數據保存到硬盤上,以防redis發生意外造成數據丟失。
目前有兩種方案,RDB方式和AOF方式。前者會根據配置的規則定時將內存中的數據持久化到硬盤上,后者則是在每次執行寫命令之后將命令記錄下來。兩種持久化方式可以單獨使用,但是通常會將兩者結合使用。按照redis作者的想法,這兩個方案最終會在以后的版本中合成一個。
?
一、快照 RDB
(1)、介紹
redis 持久化的RDB文件是經過壓縮的二進制文件,保存了內存中的鍵值對數據,存在硬盤里,防止redis數據庫出現故障時數據丟失。
當redis數據庫出現故障時,可以使用RDB文件進行還原為原先的數據庫狀態。
在實際運用中,一定要設置好規則進行定期的備份redis服務器數據,保存在其他異地服務器,一旦redis數據庫出現問題,想還原為原先的時間點,就可以使用備份RDB文件進行還原。
如果RDB文件有問題,還可以使用redis數據庫自帶的工具redis-check-dump進行檢測。
?
(2)、怎樣使用
有兩個命令可以生成RDB文件,SAVE、BGSAVE。
a)、SAVE命令會阻塞服務器進程,是在主進程中創建RDB文件,會阻塞其他的客戶端請求。
b)、BGSAVE命令會在主進程fork出的一個子進程創建RDB文件,不會阻塞客戶端請求。
c)以上兩個指令是在redis-cli客戶端直接執行命令時保存RDB文件,還可以設置SAVE命令配置,redis進行自動保存RDB文件。
save 60 100 #60秒內有100次修改,redis就會自動保存RDB文件 save 300 10 #300秒內有10次修改,redis就會自動保存RDB文件 ....可以設置多個命令,只要觸發一個save命令條件就會自動保存RDB文件。
這里設置的SAVE命令,redis其實內部是調用BGSAVE命令進行子進程創建RDB文件,確保redis主進程不會受到阻塞,可以繼續處理客戶端的讀寫請求。
?
在實際運用時,要根據場景來設定,但是一定要設置。
a)、如果本身redis數據庫讀大于寫,則設置的保存時間長久一些,不妨設置為一個小時才觸發一次創建RDB。
b)、如果redis數據庫寫比較多,而且數據比較敏感,可以設置時間短暫一些,5分鐘或者2分鐘就保存一次。
c)、數據本身比較敏感,需要進行主從備份,而主從備份依賴原理就是主redis數據庫保存RDB時,才會觸發同步從redis數據庫,這時也響應的設置時間短暫一些。
?
? (3)、原理
?僅針對配置save命令時,redis數據庫自動觸發創建RDB文件,而在redis-cli中手動執行save ,bgsave命令,內部原理也是相同的。
1、客戶端發起寫請求
2、redis會記錄寫命令計數器,并且保存一個最后保存RDB的時間
3、當redis周期性循環時,觸發設置的一個SAVE命令,redis會讀取寫命令計數器,最后保存時間
4、達到了保存RDB文件的條件,redis會fork一個子進程,其實開始執行BGSAVE命令流程
5、掃描redis數據庫的所有數據,保存到一個隨機的RDB文件
6、修改舊的RDB文件名
7、把新的隨機的RDB文件命名為正常的RDB文件即dump.rdb,并且刪除掉原先舊的RDB文件。
?如下圖所示:
?
注意事項:在執行fork是時候操作系統(類Unix操作系統)會使用寫時復制(copy-on-write)策略,即fork函數發生的一刻,父進程和子進程共享同一塊內存數據,當父進程需要修改其中的某片數據(如執行寫命令)時,操作系統會將該片數據復制一份以保證子進程不受影響,所以RDB文件存儲的是執行fork操作那一刻的內存數據。所以RDB方式理論上是會存在丟數據的情況的(fork之后修改的的那些沒有寫進RDB文件)。?
(4)、優點
a)、RDB是一種表示某個即時點的Redis數據的緊湊文件。RDB文件適合用于備份。例如,你可能想要每小時歸檔最近24小時的RDB文件,每天保存近30天的RDB快照。這允許你很容易的恢復不同版本的數據集以 ? ? ?容災。
b)、RDB非常適合于災難恢復,作為一個緊湊的單一文件,可以被傳輸到遠程的數據中心。
c)、RDB最大化了Redis的性能,因為Redis父進程持久化時唯一需要做的是啟動(fork)一個子進程,由子進程完成所有剩余工作。父進程實例不需要執行像磁盤IO這樣的操作。
d)、RDB在重啟保存了大數據集的實例時比AOF要快。
? (5)、缺點
?a)、當你需要在Redis停止工作(例如停電)時最小化數據丟失,RDB可能不太好。你可以配置不同的保存點(save point)來保存RDB文件(例如,至少5分鐘和對數據集100次寫之后,但是你可以有多個保存點)。然而,你通常每隔5分鐘或更久創建一個RDB快照,所以一旦Redis因為任何原因沒有正確關閉而停止工作,你就得做好最近幾分鐘數據丟失的準備了。?
b)、RDB需要經常調用fork()子進程來持久化到磁盤。如果數據集很大的話,fork()比較耗時,結果就是,當數據集非常大并且CPU性能不夠強大的話,Redis會停止服務客戶端幾毫秒甚至一秒。AOF也需要fork(),但是你可以調整多久頻率重寫日志而不會有損(trade-off)持久性(durability)。?
?
?
二、追加日志文件AOF
(1)、介紹
redis除了提供RDB持久化功能,還提供了AOF(append only file)持久化功能。與RDB持久化通過保存redis數據庫的鍵值對不同,AOF持久化是通過保存redis服務器所執行的寫命令來記錄數據庫狀態的。
當開啟了AO
F持久化功能時,服務器會優先從AOF文件中還原數據;如果沒有開啟AOF時,才會從RDB中還原
數據。如果AOF文件出錯了,Redis自帶的redis-check-aof工具來修復原文件。
? (2)、怎樣使用
a)、首先在配置文件中開啟AOF
appendonly yesb)、配置AOF策略,有三種策略
appendfsync no 當設置appendfsync為no的時候,Redis不會主動調用fsync去將AOF日志內容同步到磁盤,所以這一切就完全依賴于操作系統的調試了。對大多數Linux操作系統,是每30秒進行一次fsync,將緩沖區中的數據寫到磁盤上。 appendfsync everysec 當設置appendfsync為everysec的時候,Redis會默認每隔一秒進行一次fsync調用,將緩沖區中的數據寫到磁盤。但是當這一次的fsync調用時長超過1秒時。Redis會采取延遲fsync的策略,再等一秒鐘。也就是在兩秒后再進行fsync,這一次的fsync就不管會執行多長時間都會進行。這時候由于在fsync時文件描述符會被阻塞,所以當前的寫操作就會阻塞。 所以,結論就是,在絕大多數情況下,Redis會每隔一秒進行一次fsync。在最壞的情況下,兩秒鐘會進行一次fsync操作。 這一操作在大多數數據庫系統中被稱為group commit,就是組合多次寫操作的數據,一次性將日志寫到磁盤。 appednfsync always 當設置appendfsync為always時,每一次寫操作都會調用一次fsync,這時數據是最安全的,當然,由于每次都會執行fsync,所以其性能也會受到影響。?(3)、原理
1、客戶端進行寫請求
2、redis服務器收到寫請求,放入到redis服務器內存AOF緩沖區中
3、redis周期性循環中,觸發寫日志策略,去AOF寫命令緩沖區讀取數據
4、如果是appednfsync always,會在主進程中進行重寫日志,會阻塞其他的請求。如果是appendfsync everysec,會fork一個子進程進行重寫日志。如果是appendfsync?no,則依賴操作系統進行寫日志,大部分linux操作系統默認是30秒一次。
5、服務端調用write(2)?這個系統調用,將數據往系統緩沖區上寫。如果保存AOF過程到這一步時,redis數據庫出現故障,日志依然會正確的保存下去。下面的流程就由操作系統來完成了。
6、操作系統將緩沖區中的數據轉移到磁盤控制器上
7、磁盤控制器將數據寫到磁盤的物理介質中(數據真正落到磁盤上)。只有完成這一步時,機器發生故障,比如斷電,才能保證日志正確保存。
如下圖所示:
?
?
?但是這里有個問題,當寫命令越來越多,AOF文件會越來越大,所以Redis又提供了一個功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一條記錄的操作只會有一次,而不像一份老文件那樣,可能記錄了對同一個值的多次操作。其生成過程和RDB類似,也是fork一個進程,直接遍歷數據,寫入新的AOF臨時文件。在寫入新文件的過程中,所有的寫操作日志還是會寫到原來老的AOF文件中,同時還會記錄在內存緩沖區中。當重完操作完成后,會將所有緩沖區中的日志一次性寫入到臨時文件中。然后調用原子性的rename命令用新的AOF文件取代老的AOF文件。
從上面的流程我們能夠看到,RDB和AOF操作都是順序IO操作,性能都很高。而同時在通過RDB文件或者AOF日志進行數據庫恢復的時候,也是順序的讀取數據加載到內存中。所以也不會造成磁盤的隨機讀。
?
(4)、優點
1、使用AOF?Redis會更具有可持久性(durable):你可以有很多不同的fsync策略:沒有fsync,每秒fsync,每次請求時fsync。使用默認的每秒fsync策略,寫性能也仍然很不錯(fsync是由后臺線程完成的,主線程繼續努力地執行寫請求),即便你也就僅僅只損失一秒鐘的寫數據。
2、AOF日志是一個追加文件,所以不需要定位,在斷電時也沒有損壞問題。即使由于某種原因文件末尾是一個寫到一半的命令(磁盤滿或者其他原因),redis-check-aof工具也可以很輕易的修復。
當AOF文件變得很大時,Redis會自動在后臺進行重寫。重寫是絕對安全的,因為Redis繼續往舊的文件中追加,使用創建當前數據集所需的最小操作集合來創建一個全新的文件,一旦第二個文件創建完畢,Redis就會切換這兩個文件,并開始往新文件追加。
3、AOF文件里面包含一個接一個的操作,以易于理解和解析的格式存儲。你也可以輕易的導出一個AOF文件。例如,即使你不小心錯誤地使用FLUSHALL命令清空一切,如果此時并沒有執行重寫,你仍然可以保存你的數據集,你只要停止服務器,刪除最后一條命令,然后重啟Redis就可以。
?
(5)、缺點
?1、對同樣的數據集,AOF文件通常要大于等價的RDB文件。AOF可能比RDB慢,這取決于準確的fsync策略。通常fsync設置為每秒一次的話性能仍然很高,如果關閉fsync,即使在很高的負載下也和RDB一樣的快。不過,即使在很大的寫負載情況下,RDB還是能提供能好的最大延遲保證。
?
三、小結
通常來說,我們應該同時使用這兩種持久化方法。在實際配置中,最好兩者結合,AOF保證數據不會丟失,RDB進行備份數據以及提供少延遲的主從復制功能。
如果可以接受災難時有幾分鐘的數據丟失,可以只單獨使用RDB。?
單獨使用AOF也并不好,因為時常進行RDB快照非常方便于數據庫備份,啟動速度也較之快,還避免了AOF引擎的bug。?
基于這些原因,redis可能會統一AOF和RDB為一種單一的持久化模型(長遠計劃)。?
轉載于:https://my.oschina.net/haoran100/blog/712532
總結
以上是生活随笔為你收集整理的redis(7)、redis持久化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows环境下搭建React Na
- 下一篇: 十六进制转byte变负数