Python--Redis實戰:第四章:數據安全與性能保障:第3節:AOF持久化

上一篇文章: Python--Redis實戰:第四章:數據安全與性能保障:第2節:快照持久化
下一篇文章: Python--Redis實戰:第四章:數據安全與性能保障:第4節:複製

AOF持久化

簡單來講,AOF持久化會將被執行的命令寫到AOF文件的末尾,以此來記錄數據發送的變化。所以,Redis只要從頭至尾從新執行一次AOF文件包含的全部寫命令,就能夠恢復AOF文件所記錄的數據集。AOF持久化能夠經過設置代碼appendonly yes配置選項來打開。編程

文件同步:在向硬盤寫入文件時,至少會發生三件事情,當調用file.write()方法(或其它編程語言裏面的相似操做)對文件進行寫入時,寫入的內容首先會被存儲到緩衝區,而後操做系統會在未來的某個時候將緩衝區存儲的內容寫入硬盤,而數據只有在被寫入硬盤後,纔算是真正地保存到了硬盤裏面。用戶能夠經過調用file.flush()方法來請求操做系統儘快地將緩衝區存儲的數據寫入硬盤裏面,但具體地執行寫入操做仍然由系統決定。除此以外,用戶還能夠命令操做系統將文件同步(sync)到硬盤,同步操做會一直阻塞直到指定的文件被寫入硬盤爲止。當同步操做執行完畢以後,即便系統出現故障也不會對被同步的文件形成任何影響。

下表展現了appendfsync 配置選項對AOF文件的同步頻率的影響。segmentfault

選項 同步頻率
always 每一個Redis寫命令都要同步寫入硬盤。這樣作會嚴重下降Redis的速度。
everysec 每秒執行一次同步,顯示地將多個寫命令同步到硬盤。
no 讓操做系統來決定應該什麼時候進行同步。

若是用戶使用appendfsync always 選項的話,那麼每一個Redis寫命令都會被寫入硬盤,從而將發生系統崩潰時出現的數據丟失減到最少。不過遺憾的是,由於這種同步策略須要對硬盤進行大量寫入,因此Redis處理命令的速度會受到硬盤性能的限制:轉盤式硬盤(spinning disk)在這種同步頻率下每秒只能處理大約200個寫命令,而固態硬盤(solid-state drive,SSD)每秒大概也只能處理幾萬個寫命令。安全

警告:固態硬盤和appendfsync always

使用固態硬盤的用戶請謹慎使用appendfsync always選項,由於這個選項讓Redis每次只寫入一個命令,而不是像其餘appendfsync選項那樣一次寫入多個命令,這種不斷地寫入少許數據的作法有可能會引起嚴重的寫入放大(write amplification)問題,在某些環境下甚至會將固態硬盤的壽命從原來的幾年下降爲幾個月。服務器

爲了兼顧數據安全和寫入性能,用戶能夠考慮使用appendfsync everysec選項,讓Redis以每秒一次的頻率對AOF文件進行同步。Redis每秒同步一次AOF文件時的性能和不使用任何持久化特性時的性能相差無幾,而經過每秒同步一次AOF文件,Redis能夠保證,即便出現系統崩潰,用戶也最多隻會丟失一秒以內產生的數據。當硬盤忙於執行寫入操做的時候,Redis還會優雅地放慢本身的速度以便適應硬盤的最大寫入速度。app

最後,若是用戶使用appendfsync no選項,那麼Redis將不對AOF文件執行任何顯示的同步操做,而是由操做系統來決定應該在什麼時候對AOF文件進行同步。這個選項在通常狀況下不會對Redis的性能帶來影響,但系統崩潰將致使使用這種選項的Redis服務器丟失不定數量的數據。另外,若是用戶的硬盤處理寫入操做的速度不夠快的話,那麼當緩衝區被等待寫入磁盤的數據填滿時,Redis的寫入操做將被阻塞,並致使Redis處理命令請求的速度變慢。由於這個緣由,通常來講並不推薦使用appendfsync no選項,在這裏介紹了它只是爲了完整列舉appendfsync選項的可用的3個值。編程語言

雖然AOF持久化很是靈活地提供了多種不一樣的選項來知足不一樣應用程序對數據安全的不一樣要求,但AOF持久化也有缺陷:那就是AOF文件的體積大小。性能

重寫、壓縮AOF文件

AOF持久化既能夠將丟失數據的時間區間下降至1秒(甚至不丟失任何數據),又能夠在極端的時間內完成按期的持久化操做,那麼咱們有什麼理由不使用AOF持久化呢?可是這個問題實際上並無那麼簡單,由於Redis會不斷地將被執行的寫命令記錄到AOF文件裏面,全部隨着Redis不斷運行,AOF文件的體積會不斷增加,在極端狀況下,體積不斷增大的AOF文件甚至可能會用完磁盤的全部可用空間。還有另外一個問題是,由於Redis在重啓以後須要經過從新執行AOF文件記錄的全部寫命令的還原數據集,因此若是AOF文件的體積很是大,那麼還原操做執行的時間就可能會非誠長。操作系統

爲了解決AOF文件體積不斷增大的問題,用戶能夠向Redis發送bgrewriteaof命令,這個命令會經過移除AOF文件中的冗餘命令來重寫(rewrite)AOF文件,使AOF文件的體積變得儘量地小。bgrewriteaof的工做原理和bgsave建立快照的工做緣由很是類似:Redis會建立一個子進程,而後由子進程負責對AOF文件進行重寫。由於AOF文件重寫也須要用到子進程,因此快照持久化由於建立子進程而致使的性能問題和內存佔用問題,在AOF持久化中也一樣存在。更糟糕的是,若是不加以控制的話,AOF文件的體積可能會比快照的體積大好幾倍,在進行AOF重寫並刪除舊AOF文件的時候,刪除一個體積達到數十GB大的舊AOF文件可能會致使操做系統掛起數秒。進程

跟快照持久化能夠經過設置save選項來自動執行bgsave同樣,AOF持久化也能夠經過設置auto-aof-rewrite-percentage選項和auto-aof-rewrite-min-size選項來自動執行bgrewriteaof。舉個例子,假設用戶對Redis設置了配置選項auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb,而且啓用了AOF持久化,那麼當AOF文件的體積大於64MB,而且AOF文件的體積比上一次重寫以後的體積大了至少一倍(100%)的時候,Redis將執行bgrewriteaof命令。若是aof重寫執行得過於頻繁地話,那麼用戶能夠考慮將auto-aof-rewrite-percentage選項的值設置爲100以上,這種作法可讓Redis在AOF文件的體積變得更大以後才執行重寫操做,不過也會讓Redis在啓動時還原數據集所需的時間變得更長。內存

不管是使用AOF持久化仍是快照持久化,將數據持久化到硬盤上都是很是有必要的,但除了進行持續化以外,用戶還必須對持久化所得的文件進行備份(最好是備份到不一樣的地方),這樣才能儘可能避免數據丟失事故發生。若是條件容許的話,最好可以將快照文件和最新重寫的AOF文件備份到不一樣的服務器上面。

經過使用AOF持久化或者快照持久化,用戶能夠在系統重啓或者崩潰的狀況下仍讓保留數據。隨着負載量的上升、或者數據的完整性變得愈來愈重要時,用戶可能須要使用複製性。

上一篇文章: Python--Redis實戰:第四章:數據安全與性能保障:第2節:快照持久化
下一篇文章: Python--Redis實戰:第四章:數據安全與性能保障:第4節:複製
相關文章
相關標籤/搜索