redis靈魂拷問:聊一聊AOF日誌重寫

目錄redis

AOF簡介緩存

什麼是AOF重寫app

AOF重寫對性能的影響ide


本文咱們來聊一聊AOF日誌重寫性能

AOF簡介

redis的AOF日誌,是redis持久化的一種方式,它是一種write after log,即先執行命令後記錄日誌。這樣的好處是日誌不會記錄執行失敗的命令,同時記錄日誌不會阻塞當前命令執行。操作系統

 記錄AOF是在主線程中執行的,因此也會阻塞主線程。這個跟AOF的寫回策略有關,這個配置項參數叫appendfsync,在redis.conf文件中,默認值是everysec。下面是3種寫回策略的比較:線程

寫回策略3d

策略說明日誌

優勢blog

缺點

always

執行命令後同步寫盤

基本不丟失命令

性能損耗大

everysec

每秒寫一次盤

比always性能損耗小

可能會丟失1s命令

no

由操做系統控制寫盤

性能損耗最新

可能會丟失不少命令

這樣,咱們就須要在性能和可靠性之間作一些取捨了。

當redis上執行的命令愈來愈多,AOF日誌文件會變得很大,這樣AOF文件追加命令會很慢,並且操做系統對文件大小也有必定的限制,再者若是使用AOF作主從同步或數據恢復的話,由於命令記錄太多會致使耗時很長。redis解決這個問題的手段就是AOF日誌重寫。

什麼是AOF重寫

在redis.conf文件中,有下面2個參數來控制AOF重寫:

auto-aof-rewrite-percentage 100 #AOF文件大小較上次重寫超過100%時進行重寫
auto-aof-rewrite-min-size 64mb #aof文件大小超過64m時重寫

下面咱們執行6條命令:

192.168.59.146:6379> set name jinjnzhu
OK
192.168.59.146:6379> set password 123456
OK
192.168.59.146:6379> set name jinjunzhu1
OK
192.168.59.146:6379> set password 1234567
OK
192.168.59.146:6379> set name jinjunzhu2
OK
192.168.59.146:6379> set password 12345678
OK

以後咱們查看name和password的值:

192.168.59.146:6379> get name
"jinjunzhu2"
192.168.59.146:6379> get password
"12345678"

這2個key的值被賦予了最新的一次賦值,雖然咱們執行了6條命令,可是AOF重寫後日志文件就剩了最後2條命令。

AOF重寫對性能的影響

在上小節的介紹中,若是AOF文件較上次重寫超過了100%,就要進行重寫。可是若是日誌特別大,AOF重寫後把日誌寫會磁盤也是一個很是耗時的操做,這是否會阻塞主線程呢?

  • AOF重寫並非在主線程中,而是redis會fork一個bgrewriteaof子進程,這樣就不會阻塞主線程執行了。
  • fork子進程的過程是要在主線程中執行的,這時候主線程須要拷貝內存頁表,這個頁表記錄了虛擬內存和物理內存的映射關係,若是內存很大,拷貝過程花費的時間就會很大,而這個拷貝過程當中主線程是阻塞的。
  • fork子進程完成後,主線程和bgrewriteaof子進程使用的是同一起內存空間,這時若是有新的寫請求到來,而且寫命令是已經存在的key,主線程會使用CopyOnWrite的方式,爲這個key申請新的內存空間,進行寫操做。若是這個key是一個bigkey,那也會耗時不少。

 下面我畫了一個簡單的圖,主線程fork出bgrewriteaof子進程時,複製了一個頁表給子進程用,跟本身指向相同的內存空間。可是AOF重寫過程當中收到了foo這個key的寫命令,這是主線程須要拷貝一份數據到新的內存空間進行修改。

在AOF重寫的過程當中,若是有新的寫命令到來了,會影響AOF重寫嗎? 固然不會,新的寫命令不只會記錄到AOF日誌的緩存區,還會記錄到重寫的新AOF日誌緩存區,這樣當AOF重寫結束後,把從新緩存區數據寫到新AOF文件,就不會丟失了。 

相關文章
相關標籤/搜索