redis 硬件要求_Redis持久化机制
介紹
Redis所有的數據都保存在內存中,數據的更新將異步的保存到硬盤上,當需要恢復數據時,從硬盤上將數據再讀取到內存中,這就是Redis的持久化過程。主流的持久化方式有兩種:
快照:MySQL的Dump以及Redis的RDB等
寫日志:MySQL的Binlog,Hbase的HLong以及Redis的AOF等
一、Redis的持久化機制
Redis將所有的數據都存儲在內存中,那么如果服務器重啟了,Redis中的數據怎么恢復呢?
為了使Redis在重啟之后仍能保證數據不丟失,需要將數據從內存中同步到硬盤中。Redis支持兩種方式的持久化,一種是RDB方式,一種是AOF方式。可以單獨使用其中一種或將二者結合使用。
二、RDB方式
RDB方式的持久化是通過快照(snapshotting)完成的,當符合一定條件時Redis會自動將內 存中的所有數據進行快照并存儲在硬盤上。進行快照的條件可以由用戶在配置文件中自定 義,由兩個參數構成:時間和改動的鍵的個數。當在指定的時間內被更改的鍵的個數大于指定 的數值時就會進行快照。RDB是Redis默認采用的持久化方式,在配置文件中已經預置了3個條 件:
save 900 1 save 300 10 save 60 10000Redis默認會將快照文件存儲在當前目錄的dump.rdb文件中,可以通過配置dir和 dbfilename兩個參數分別指定快照文件的存儲路徑和文件名。最佳配置實踐:
dbfilename?dump-${port}.rdb快照的過程如下:
Redis使用fork函數復制一份當前進程(父進程)的副本(子進程)
父進程繼續接收并處理客戶端發來的命令,而子進程開始將內存中的數據寫入硬盤中的臨時文件
當子進程寫入完所有數據后會用該臨時文件替換舊的RDB文件,至此一次快照操作完 成。
寫時復制(copy-on-write)策略:在執行fork的時候操作系統會使用寫時復制策略,即fork函數發生的一刻父子進程共享同一內存數據,當父進程要更改其中某片數據時(如執行一個寫命令),操作系統會將該片數據復制一份以保證子進程的數據不受影響,所以新的RDB文件存儲的是執行fork一刻的內存數據。
Redis在進行快照的過程中不會修改RDB文件,只有快照結束后才會將舊的文件替換成新的,也就是說任何時候RDB文件都是完整的。這樣我們可以通過定時備份RDB文件來實現Redis數據庫備份。
RDB文件是經過壓縮的二進制格式:
可以配置rdbcompression參數以禁用壓縮節省CPU占用,所以占用的空間會小于內存中的數據大小,更加利于傳輸。其他兩個配置參數:
stop-writes-on-bgsave-error yes // bgsave發生錯誤,停止寫入rdbchecksum?yesrdbcompression yes除了自動快照,還可以手動發送SAVE或BGSAVE命令讓Redis執行快照,兩個命令的區別:
SAVE是由主進程進行快照操作,會阻塞住客戶端其他請求,不會消耗額外的內存
BGSAVE會通過fork子進程進行快照操作,不會阻塞客戶端命令,fork會消耗內存
兩者的時間復雜度都是o(n)
RDB文件觸發機制
除了前面介紹的三種:自動,save,bgsave外,還有下面幾種方式也會生成RDB文件:
全量復制:主從復制中,主節點會自動生成RDB文件給從節點同步使用
debug reload
shutdown
Redis啟動后會讀取RDB快照文件,將數據從硬盤載入到內存。通常將一個記錄一千萬個字符串類型鍵、大小為1GB的快照文件載入到內存中需要花費20~30秒鐘。通過RDB方式實現持久化,一旦Redis異常退出,就會丟失最后一次快照以后更改的所有數據。如果數據很重要以至于無法承受任何損失,則可以考慮使用AOF方式進行持久化。
RDB方式的優點:
性能最大化,fork子進程來完成寫操作,讓主進程繼續處理命令,使用單獨子進程來進行持久化,保證了redis的高性能
當重啟恢復數據的時候,數據量比較大時,Redis直接解析RDB二進制文件,生成對應的數據存儲在內存中,比AOF的啟動效率更高
RDB方式的缺點:
數據安全性低,RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失,所以這種方式更適合數據要求不嚴謹的時候
linux fork之后,kernel把父進程中所有的內存頁的權限都設為read-only,然后子進程的地址空間指向父進程。當父子進程都只讀內存時,相安無事。
當其中某個進程寫內存時,CPU硬件檢測到內存頁是read-only的,于是觸發頁的異常中斷(page-fault),陷入kernel的一個中斷例程
中斷例程中,kernel的copyonwrite機制就會把觸發的異常的頁復制一份,于是父子進程各自持有獨立的一份,如果這時有大量的寫入操作,會產生大量的分頁錯誤,這樣就得耗費不少性能在復制上
三、AOF方式
默認情況下Redis沒有開啟AOF(append only file)方式的持久化,可以通過appendonly參數開啟:
appendonly yes開啟AOF持久化后每執行一條會更改Redis中的數據的命令,Redis就會將該命令寫入硬盤中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數設置的,默認的文件名是appendonly.aof,可以通過appendfilename參數修改:
appendfilename appendonly.aof下面介紹AOF持久化的具體實現,假設在開啟AOF持久化的情況下執行了如下4個命令:
SET foo 1 SET foo 2 SET foo 3 GET fooRedis會將前3條命令寫入AOF文件中,此時AOF文件中的內容如下:
*2$6SELECT$10*3$3set$3foo$11*3$3set$3foo$12*3$3set$3foo$13可見AOF文件是純文本文件,其內容正是Redis客戶端向Redis發送的原始通信協議的內容。
這里有一個問題是前2條命令其實都是冗余的, 因為這兩條的執行結果會被第三條命令覆蓋。隨著執行的命令越來越多,AOF文件的大小也會越來越大。實際上每當達到一定條件時Redis就會自動重寫AOF文件,這個條件可以在配置文件中設置:
auto-aof-rewrite-percentage?100?//代表當前AOF文件空間和上一次重寫后AOF文件空間的比值auto-aof-rewrite-min-size?64mb?//表示運行AOF重寫時文件最小體積,默認64MBauto-aof-rewrite-percentage參數的意思是當目前的AOF文件大小超過上一次重寫時的AOF 文件大小的百分之多少時會再次進行重寫,如果之前沒有重寫過,則以啟動時的AOF文件大小為依據
auto-aof-rewrite-min-size參數限制了允許重寫的最小AOF文件大小,通常在AOF文 件很小的情況下即使其中有很多冗余的命令我們也并不太關心
除了讓Redis自動執行重寫外,還可以主動使用BGREWRITEAOF命令手動執行AOF重寫。
AOF文件重寫后的內容為:
*2$6SELECT$10*3$3set$3foo$13在啟動時Redis會逐個執行AOF文件中的命令來將硬盤中的數據載入到內存中,載入的速度相較RDB會慢一些。下面是AOF重寫的流程:
注意:雖然每次執行更改數據庫內容的操作時,AOF都會將命令記錄在AOF文件中,但是由于操作系統的緩存機制,數據并沒有真正地寫入硬盤,而是進入了系統的硬盤緩存。在默認情況下系統每30秒會執行一次同步操作,以便將硬盤緩存中的內容真正地寫入硬盤,在這30秒的過程中如果系統異常退出則會導致硬盤緩存中的數據丟失。一般來講啟用AOF持久化的應用都無法容忍這樣的損失,這就需要Redis在寫入AOF文件后主動要求系統將緩存內容同步到硬盤中。在Redis中我們可以通過appendfsync參數設置同步的時機:
# appendfsync always appendfsync everysec # appendfsync no默認情況下Redis采用everysec 規則,即每秒執行一次同步操作
always表示每次執行寫入都會執行同步,這是最安全也是最慢的方式
no表示不主動進行同步操作,而是完全交由操作系統來做(即每30秒一次),這是最快但最不安全的方式
AOF追加阻塞
主線程為了達到每秒刷盤的策略,它會執行AOF追加阻塞,流程如下:
所以可能產生的問題:
主線程阻塞,主線程需要執行我們日常命令的處理,所以主線程不能阻塞
每秒刷盤的策略不是只丟失1秒的數據,實際上可能丟失2秒的數據
AOF阻塞定位可以通過Redis日志:
Asynchronous AOF fsync is taking too long (disk is busy?).Writing?the?AOF?buffer?without?waiting?for?fsync?to?complete,this?may?slow?down Redis也可以通過Redis命令:
127.0.0.1:6379>?info?persistence......aof_delayed_fsync:100......也可以通過top命令觀察硬盤IO資源比較緊張的情況:
AOF配置參數最佳實踐
appendonly yesappendfilename?appendonly-${port}.aofappendfsync everysec no-appendfsync-on-rewrite?yes?//?aof重寫時是否做aof的append操作(否)Redis允許同時開啟AOF和RDB,既保證了數據安全又使得進行備份等操作十分容易。此時重新啟動Redis后Redis會使用AOF文件來恢復數據,因為AOF方式的持久化可能丟失的數據更少。
AOF方式的優點:
數據安全
AOF方式的缺點:
數據集大的時候,比RDB啟動效率低
fork操作介紹
fork操作只是做一個內存頁(4K)的拷貝而不是拷貝整個內存,所以在大部分情況下是非常快的。info:latest_fork_usec可以查看Redis持久化的時間。改善fork可以通過:
使用物理機或者高效支持fork操作的虛擬化技術
控制Redis實例最大可用內存:maxmemory
合理配置Linux內存分配策略:vm.overcommit_memory=1,當沒有足夠內存去做內存分配的時候就不去分配內存,默認值是0
降低fork頻率,例如放寬AOF重寫機制的觸發時機,減少不必要的全量復制
子進程開銷和優化
1. CPU
開銷:RDB和AOF文件生成,屬于CPU密集型,大量寫操作集中在這個時候
優化:不做CPU綁定,不和CPU密集型部署
2.?內存
開銷:copy-on-write,父子進程共享一個物理內存頁,寫時會fork一個副本
優化:不允許單機多部署時大量產生重寫
3.?硬盤
開銷:RDB和AOF文件寫入,可以結合iostat,iotop分析
優化:不要和高硬盤負載服務部署一起:存儲服務,消息隊列等;no-appendfsync-on-rewrite=yes;大寫入量可以選用ssd;單機多實例持久化文件目錄可以考慮分盤
四、RDB與AOF對比
| 命令 | RDB | AOF |
| 啟動優先級 | 低 | 高 |
| 體積 | 小 | 大 |
| 恢復速度 | 快 | 慢 |
| 數據安全性 | 丟數據 | 根據策略決定 |
| 操作量級 | 重 | 輕 |
五、混合持久化
可以通過參數設置:aof-use-rdb-preamble yes開啟。
加載時,首先會識別AOF文件是否以REDIS字符串開頭,如果是,就按RDB格式加載,加載完RDB之后繼續按照AOF格式加載剩余部分。混合式持久化方案兼顧了RDB的速度和AOF的安全性。
推薦閱讀
Redis值類型之sorted set
Redis數據結構與內部編碼,你知道多少?
看完本文有收獲?請轉發分享給更多人
關注「并發編程之美」,一起交流Java學習心得
總結
以上是生活随笔為你收集整理的redis 硬件要求_Redis持久化机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hi3516配置wifi_HISI 35
- 下一篇: mysql查询父子关系树_swt 生成树