Java學習筆記:Redis的持久化
fork()系統呼叫:
這裡很突兀的來個fork()系統呼叫原因是應為:Redis的單執行緒的,那如果主執行緒去做這種耗時的IO同步操作時,Redis整體的效能會被拖垮的。
fork()它是一個系統呼叫,一般用它來建立一個和當前程式一模一樣的子程式。當在程式中呼叫它時,系統為新的程式分配儲存、資源,將原程式中的值也複製給他。
fork()函式呼叫一次會返回兩次,在父程式得到的返回值是子程式的pid,在子程式中得到的是0,出錯則返回負數。
Redis的實現是通過fork()系統呼叫建立一個子程式。 由這個子程式去負責執行這些耗時的IO操作,父子程式會共享記憶體,然後被共享的這塊記憶體不可寫,新的資料寫入到新的記憶體檔案中
RDB:
寫RDB檔案是Redis的一種持久化方式。在指定的時間間隔內將記憶體中的資料寫入到磁碟,RDB檔案是一個緊湊的二進位制檔案,每一個檔案都代表了某一個時刻(執行fork的時刻)Redis完整的資料快照,恢復資料時,將快照檔案讀入記憶體即可。
RDB持久化的詳細過程:
Redis會通過系統呼叫fork()出一個子程式,父子程式是會共享記憶體的,父程式和子程式共享的這塊記憶體就是在執行fork操作那個時刻的記憶體快照。由linux的copy on write機制將父子程式共享的這塊記憶體標記為只讀狀態。
此時對子程式來說,它的任務就是將這塊只讀記憶體中的資料儲存成RDB檔案。
對父程式來說它是有可能收到寫命令的,當父程式嘗試往這個加了只讀狀態的記憶體地址寫入資料時,就會觸發保護異常,執行linux的 copy on write,也就是將原來記憶體對應的資料頁複製出來一份後,然後對這個副本進行修改。
這裡就會出現一個丟資料的概念:你想,fork出來的子程式將要儲存的資料是執行fork系統呼叫那個時刻的記憶體中的資料,很快這個記憶體就被標記為只讀了,後續的增量資料沒有寫入到這個只讀記憶體中,那就算是RDB成功生成了,然後好巧,Redis掛了,這些增量的資料就會丟(所以得使用AOF輔助)
第二種RDB出現資料的丟失的情況是:RDB過程中,直接失敗了,檔案都沒生成,不光是增量資料,原來的資料都丟了。
RDB相關配置如下
# 把下面的註釋開啟就會禁用掉RDB的持久化策略
# save ""
# 快照相關,指的是在規定的時間內執行了多少次操作才會持久化到檔案
save 900 1 # 900秒內1次
save 300 10 # 300秒內10次
save 60 10000 # 60秒內1萬次
# 持久化出錯了,是否讓redis繼續工作
stop-writes-on-bgsave-error yes
# 是否壓縮RBD檔案(redis會採用LZF壓縮演算法進行壓縮)需要消耗CPU資源
rdbcompression yes
# 儲存rbc檔案時是否檢驗rbd檔案格式
# 使用CRC64演算法進行資料校驗,但是這樣會增加大約 10%的效能消耗
rdbchecksum yes
# dump DB的檔名
dbfilename dump.rdb
# rdb檔案的持久化目錄(當前目錄)
dir ./
觸發儲存RDB檔案4種情況
- 手動執行save命令、bgsave
- 滿足配置檔案中配置的save相關配置項時,自動觸發
- 手動執行flushall
- 關閉redisshutdown
如何讓redis載入rdb檔案?
只需要將rdb檔案放在redis的啟動目錄下,redis其中時會自動載入它
RDB模式的優缺點:
優點:RDB過程中,由子程式代替主程式進行備份的IO操作。保證了主程式仍然提供高效能的服務。適合大規模的資料備份恢復過程。
缺點:
- 預設情況下,它是每隔一段時間進行一次資料備份,所以一旦出現最後一次持久化的資料丟失,將丟失大規模的資料。
- fork()子程式時會佔用一定的記憶體空間,如果在fork()子程式的過程中,父程式夯住了,那也就是redis卡住了,不能對外提供服務。所以不要讓生成RDB檔案的時間間隔太長,不然每次生成的RDB檔案過大對Redis本身也是有影響的。
AOF:
AOF是什麼?
Append Only File,他也是Redis的持久化策略。即將所有的寫命令都以日誌的方式追加記錄下來(只追加,不修改),恢復的時候將這個檔案中的命令讀出來回放。
當我們執行 flushall 命令,清空了redis在記憶體中的資料,appendonly.aof 同樣會記錄下這條命令,所以,我們想恢復資料的話,需要去除 appendonly.aof 裡面的 flushall 命令
AOF相關的配置
# 預設不開啟aof
appendonly no
# aof檔名
appendfilename "appendonly.aof"
# redis通過fsync()呼叫告訴作業系統實際在磁碟上寫入資料
# aof檔案落盤的策略
# appendfsync always 每次發生資料變更,立刻記錄到磁碟,但是導致redis吞吐量降低
# appendfsync everysec 可能會丟失1秒的資料
# appendfsync no
appendfsync everysec
# 當時用bfwriteaof時,fork一個子程式寫aof檔案,就算aof檔案很大,也不會阻塞主程式
# 意外情況:但是當主程式、子程式同時寫aof檔案時,可能會出現由於子程式大量的IO操作阻塞主程式
# 當出現這種意外情況時:設定這個引數為no,可以保證資料不會丟失,但是得容忍主程式被阻塞
# 當出現這種意外情況時:設定這個引數為yes,主程式不會被阻塞主,但是不保證資料安全性
# 綜上:如果應用無法忍受延遲:設定為yes。無法忍受資料丟失:設定為no
no-appendfsync-on-rewrite no
# 在當前aof檔案的體積超過上次aof檔案的體積的100%時,寫新檔案
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb # 最開始的aof檔案體積至少達到60M時才重寫
# 回放aof檔案時,如果最後一條命令存在問題,是否允許忽略
aof-load-truncated yes
# 是否允許AOF和RDB這兩種持久化方式並存
aof-use-rdb-preamble yes
當aof檔案出錯怎麼辦?
redis為我們提供了修復aof檔案的工具
[root@instance-lynj0v9k-19 bin]# redis-check-aof --fix appendonly.aof
aof模式的優缺點 優點:
- aof是用追加的形式寫,沒有隨機磁碟IO那樣的定址開銷,效能還是比較高的。
- aof可以更好的保護資料不丟失或者儘可能的少丟失:設定讓redis每秒同步一次資料,即使redis當機了,最多也就丟失1秒的資料。
- 即使aof真的體積很大,也可以設定後臺重寫,不影響客戶端的重寫。
- aof適合做災難性的誤刪除緊急恢復:比如不小心執行了flushall,然後可以在發生rewrite之前 快速備份下aof檔案,去掉末尾的 flushall,通過恢復機制恢復資料
缺點:使用aof一直追加寫,導致aof的體積遠大於RDB檔案的體積,恢復資料、修復的速度要比rdb慢很多。
aof的重寫
AOF採取的是檔案追加的方式,檔案的體積越來越大,為了優化這種現象,增加了重寫機制,當aof檔案的體積到達我們在上面的配置檔案上的闋值時,就會觸發重寫策略,只保留和資料恢復相關的命令
手動觸發重寫
# redis會fork出一條新的程式
# 同樣是先複製到一份新的臨時檔案,最後再rename,遍歷每一條語句,記錄下有set的語句
bgrewriteaof
RDB和AOF的選擇:
- 如果我們的redis只是簡單的作為快取,那兩者都不要也沒事
- 如果資料需要持久化,那不要僅僅使用RDB,因為一旦發生故障,你會丟失很多資料
- 同時開啟兩者: 在這種情況下,redis優先載入的是aof,因為它的資料很可能比rdb更全,但是並不建議只是用aof,因為aof不是那麼的安全,很可能存在潛在的bug
推薦:
- 建議在從機slave上只備份rdb檔案,而且只要15分鐘備份一次就夠了。
- 如果啟動了aof,我們儘量減少rewrite的頻率,基礎大小設定為5G完全可以,起步也要3G。
- 如果我們不選擇aof, 而是選擇了主從複製的架構實現高可用同樣可以,能省掉一大筆IO操作,但是意外發生的話,會丟失十幾分鐘的資料。
相關文章
- Redis 學習筆記(篇七):Redis 持久化Redis筆記持久化
- Redis學習筆記六:持久化實驗(AOF,RDB)Redis筆記持久化
- Redis 學習筆記(四)RDB 和 AOF 持久化機制Redis筆記持久化
- redis學習手記(二)持久化方式Redis持久化
- Redis基礎知識(學習筆記16--持久化 (2))Redis筆記持久化
- Redis基礎知識(學習筆記15--持久化 (1))Redis筆記持久化
- Redis基礎知識(學習筆記17--持久化 (3))Redis筆記持久化
- 「學習筆記」可持久化線段樹筆記持久化
- Adaptive AUTOSAR 學習筆記 15 - 持久化 PersistencyAPT筆記持久化
- 深入學習 Redis(2):持久化Redis持久化
- Redis學習筆記(Jedis&資料型別&持久化&主從複製)Redis筆記資料型別持久化
- redis學習筆記4: 在Java中操作RedisRedis筆記Java
- Unity學習筆記--資料持久化之PlayerPrefs的使用Unity筆記持久化
- 【Redis 系列】redis 學習八,redis 持久化 RDB 和 AOFRedis持久化
- redis學習筆記Redis筆記
- redis學習筆記(三)–Redis的功能Redis筆記
- Redis學習筆記(三)redis 的鍵管理Redis筆記
- Redis 學習筆記命令Redis筆記
- Redis的持久化Redis持久化
- Redis 的持久化Redis持久化
- redis學習筆記1: Redis入門Redis筆記
- Redis學習筆記【01】 - 安裝RedisRedis筆記
- (Redis學習筆記):Redis解決方案Redis筆記
- Redis學習筆記(一)——初識RedisRedis筆記
- Redis學習筆記(三) 字典Redis筆記
- Redis學習整理筆記02Redis筆記
- Redis阻塞(學習筆記七)Redis筆記
- redis - 學習筆記回顧Redis筆記
- JAVA學習筆記Java筆記
- K8S學習筆記之Kubernetes資料持久化方案K8S筆記持久化
- 《JAVA學習指南》學習筆記Java筆記
- 【Redis學習筆記】2018-07-10 Redis指令學習3Redis筆記
- 【Redis學習筆記】2018-07-11 Redis指令學習5Redis筆記
- [Redis]持久化Redis持久化
- redis持久化Redis持久化
- Redis - 持久化Redis持久化
- Redis 持久化Redis持久化
- Redis持久化——記憶體快照(RDB)Redis持久化記憶體