Redis的持久化

2021-09-10 01:36:42 字數 2601 閱讀 5455

我們都知道,redis的資料都是儲存在記憶體裡面的,導致了redis有如下特點

1.由於記憶體的容量較小,並且速度很快,所以redis相對於mysql、orcle等資料庫相比,儲存的容量較小,但是io速度特別快。

2.由於記憶體的臨時儲存性,在機器斷電之後記憶體裡的內容將會丟失,若redis沒有持久化,則資料也將全部丟失。

簡而言之,redis持久化是保證redis資料不會因為故障而丟失的一種機制。

如圖,redis的持久化機制一共有兩種:一種是快照的形式,另一種是aof日誌。下面將分別介紹這兩種機制

快照就是redis把記憶體中的資料通過磁碟io持久化到硬碟當中,預設生成為dump.db為檔名的檔案,裡面資訊是已經被序列化的文字。

redis的快照是全量備份,所謂全量備份就是對某一時間點上的所有資料進行乙個完全拷貝。快照儲存的資料是一種二進位制序列化的形式,在儲存上是非常緊湊的

redis是單執行緒的程式,意味著在這個執行緒當中需要負責多個客戶端套接字的併發操作和記憶體邏輯的讀寫操作。在伺服器請求的同時,redis還要進行記憶體的快照操作,該操作需要進行檔案的io,可是檔案io操作不能使用多路復用api,這就意味這伺服器在處理請求的同時還要對io進行操作,嚴重影響到了伺服器的效能。

還有另乙個問題,為了不堵塞線上的業務,redis需要進行一邊持久化一邊處理請求,在持久化未完成的同時,很可能資料結構已經被請求所改變,比如乙個資料正在進行持久化(未完成),結果乙個請求來了,把資料給刪了,這將會出現很嚴重的問題。

redis的解決策略是使用作業系統的多程序cow機制來實現快照持久化。下面將做出一些解釋

在持久化的時候,redis會呼叫glibc函式的fork產生乙個子程序進行快照的處理,而父程序則單獨處理請求操作。子程序和父程序共享記憶體塊裡面的資料,所以在分離程序的時候,記憶體基本上不會進行增長。

pid = os.fork()

if pid > 0: #當前為父程序,返回為子程序pid

handle_client_requests() #父程序繼續處理客戶端請求

if pid == 0: #當前為子程序

handle_snapshot_write() #子程序處理快照寫磁碟

if pid < 0 : #記憶體資源不足

#fork error

子程序進行持久化的時候,並不會修改到記憶體的資料結構,僅僅是對記憶體進行遍歷讀取,然後序列化到磁碟上。修改資料結構的操作在於父程序的請求處理中

由前文所述,redis是使用多程序的cow機制來實現快照的

當資料被父程序修改的時候,資料段將會拷貝出乙份需要修改的**段的副本出來,然而並不影響子程序對原有的資料段的遍歷,然後父程序進行對副本資料的修改。當父程序不斷對資料進行改寫的時候,越來越多的資料段進行複製,這樣會不斷的產生新的記憶體,但是值得注意的一點就是redis記憶體中的冷資料往往比較多,所以被分離的資料總體來說還是比較少的,假設在最差的情況下,記憶體的增長量也是原資料的兩倍(全部資料被修改)。

當建立好快照之後,快照會跟著資料的變化,一旦監控到原資料被改寫後,則把原資料拷貝到乙個新的資料塊上,然後將最新的資料覆蓋到原資料當中完成更新操作,這樣下來,所有的原資料塊成為原資料卷,所有新資料塊成為了快照卷,由此看來快照操作有乙個很大的缺點那就是降低了寫的效能,因為每次更新資料都進行了兩次的寫操作。

子程序的資料是不會由於新請求而變化,相當於在某一時刻用相機對資料進行快速的拍了下來,這大概是叫快照的原因了,是資料對時間的定格。

aof日誌是連續的增量備份,它的內容記錄著對記憶體資料修改的指令文字,隨著日誌的長期執行,資料文字會變得非常龐大,資料庫在重啟的時候要對日誌進行載入,也是對指令的重放,如果不進行日誌**的話該操作會耗時很長,所以要定期對aof進行重寫。

在用指令對資料結構進行修改的時候,進行一系列的引數校驗、邏輯處理過後,該指令會被記錄到aof日誌當中,所謂的重放,也就是對aof日誌中指令的順序執行,來恢復redis例項中的記憶體資料結構的狀態。該處理的特點是「先執行,後儲存」,像leveldb、hbase等屬於「先儲存,後執行「

redis可以通過bgrewriteaof指令對aof日誌進行**,其原理是開闢乙個記憶體對redis的資料結構進行遍歷,從而轉換成一系列的指令,序列化到乙個新的日誌檔案中,序列好之後,如果再對資料結構進行修改則指令直接追加到新的日誌檔案中,追加完之後則代替舊的日誌檔案,完成了**。

當程式對aof檔案進行寫操作的時候,是將內容先寫到了乙個核心快取當中,再從核心快取中把資料重新整理到日誌檔案磁碟中。

如果內容在寫到核心快取中還沒來得及重新整理到磁碟中,機器突然宕機了,檔案將會被丟失。redis同樣考慮到了這點。linux提供了乙個fsync函式可以將指定的內容強制從記憶體重新整理到磁碟當中。只要redis程序實時的呼叫fsnyc可以保證aof不會被丟失,但是!fsnyc是乙個磁碟io操作,所以會特別的慢(比如使用來乙個指令就呼叫一次fsync的策略),如果呼叫的特別頻繁的話會嚴重影響到redis的效能。

在生產環境中,redis通常是每隔一秒鐘執行一次fsync操作,這樣在資料安全性和效能之間做了乙個折中。在保證效能的同時,盡可能的減少資料丟失。

redis持久化 AOF持久化

1.aof持久化原理 aof持久化會將被執行的寫命令寫到aof檔案的末尾。在恢復的時候,redis只要從頭到尾重新執行一次aof檔案包含的所有寫命令 2.配置選項 固態硬碟禁用always選項,在某些情況頻繁讀寫會大大降低固態硬碟的壽命 4.aof檔案的重寫和壓縮 aof檔案裡面記錄了所有的命令而不...

redis的持久化

redis有兩種持久化策略 rdb 是redis的預設持久化級制。相當於照快照,儲存的是一種狀態。優點 快照速度極快 還原資料速度極快 適用於災難備份 缺點 小記憶體機器不適合,適用於記憶體充裕的計算機 rdb機制符合要求就會找快照 隨時啟動,會突然的占用一部分系統資源 伺服器正常關閉 key滿足一...

redis的持久化

該持久化方式實際是在redis內部乙個定時器事件,每隔固定時間去檢查當前資料發生的改變次數與時間是否滿足配置的持久化觸發的條件,如果滿足則通過作業系統fork呼叫來建立出乙個子程序,這個子程序缺省會與父程序共享相同的位址空間,這時就可以通過子程序來遍歷整個記憶體來進行儲存操作,而主程序則仍然可以提供...