1.? 什么是 AOF
AOF 是 append only file,AOF 文件中記錄了每次的操作指令,在啟動 Redis 時,會將 AOF 文件中的數據讀取出來以恢復數據。
2. 開啟 AOF
Redis 默認關閉 AOF,可以通過將 Redis 配置文件中的?appendonly 設置為 yes,這樣就開啟了 AOF,此時 RDB 就會關閉,只能使用 AOF 和 RDB 中的一個。
3. AOF 的工作流程
用戶執行指令后,會將該指令寫入到 AOF 緩沖區(aof_buf,即一段內存緩沖區),當新的指令數量達到一定時,就會將這些新的指令寫入到 AOF 文件中,再保存至硬盤。
注意:
- 在向硬盤中寫數據時,不是用戶執行了一條新指令就寫一條,而是將新指令積累到一定數量后統一進行寫入,這樣可以減少寫硬盤的次數,從而降低寫硬盤對 Redis 性能的影響。
- Redis 將 AOF 文件寫入硬盤是將文件中的數據追加到原文件后,屬于順序讀寫,速度相對較快。
- 如果在寫 AOF 緩沖區時主機突然掉電了,由于數據是存儲在硬盤上的,那么這些數據也會消失不見。這就與 Redis 寫 AOF 文件的頻率有關。
4.?AOF 緩沖區同步文件策略
上面我們談到,當由于有些數據是存儲在 AOF 緩沖區的,那么就有可能因為某些原因導致內存上的數據消息,我們可以通過修改緩沖區的刷新策略盡可能地減少上述的問題。
Redis 提供的刷新策略有三種:
- always:只要用戶執行了一條指令,就將這條指令寫入硬盤;
- everysec: Redis 默認策略,以 1s 為刷新區間,每隔 1s 就將新指令寫入硬盤;
- no:操作系統自行刷新緩沖區。
三種刷新策略的比較:
- always:刷新頻率最高,數據可靠性最高,但由于涉及到頻繁寫硬盤,就會降低 Redis 性能;
- everysec: 刷新頻率相較于 always 較低,數據可靠性也會降低,但是由于寫硬盤的頻率降低了,Redis 的性能也會提高;
- no:刷新頻率最低,數據可靠性最差,寫硬盤的頻率最低,Redis 性能最高。
5. AOF 文件重寫機制
隨著執行的指令數越來越多,那么寫入 AOF 文件中的數據也就會越來越多,導致 AOF 文件變得越來越大。由于 Redis 在啟動時會將 AOF 中的數據取出,就導致 Redis 的啟動時間變長。
- Redis 將AOF 文件進行壓縮,將多條指令壓縮為一條指令,如:set key1 aaa、set key1?bbb、set key1 ccc,那么就會將這三條指令壓縮為 set key1 ccc,以此類推;
- Redis 也會將 AOF 中已經超時的數據刪除,以減小文件的大小;
- 刪除無效指令,如:del、keys 等。
較小的 AOF 文件會加快 Redis 程序的啟動速度,也會減少硬盤的占用。
6. 觸發 AOF 重寫機制
6.1 手動觸發
- 手動執行 bgrewriteaof 指令
6.2 自動觸發
- auto-aof-rewrite-min-size:表示觸發重寫時 AOF 的最小文件大小,默認為 64MB。
- auto-aof-rewrite-percentage:代表當前 AOF 占用大小相比較上次重寫時增加比例。
7. AOF 重寫流程
- 與 RDB 一樣,父進程首先會創建子進程,子進程將指令存入新 AOF 文件中,父進程依然接收客戶端請求,子進程進行重寫操作;
- 由于在子進程進行重寫時,依然會有新的指令依次執行,于是父進程會將新的指令同時寫入aof_buf 和 aof_rewrite_buf(也是一段內存緩沖區);
- 當子進程完成復制后,就會給父進程發送信號,父進程就會將 aof_rewrite_buf 中的數據寫入到新 AOF 文件中;
- aof_rewrite_buf 中的數據寫入完成后,就會將新的 AOF 文件代替舊的 AOF 文件。
注意:
- 子進程在進行重寫時,只是將 Redis 中的數據取出來以 AOF 文件的形式存入新 AOF 文件,并不關系指令的操作流程;
- AOF 文件是以文本形式存儲數據的,而 RDB 文件是以二進制文件存儲數據的,相比之下,讀取 RDB 文件中的數據比讀取 AOF 文件中的數據速度更快;
- 既然父進程已經將新的指令寫入到新的 AOF 文件中,那為什么還要重寫舊 AOF 文件?這是因為若在子進程重寫的過程中,如果發生主機掉電等問題,由于新 AOF 文件是存儲在內存中的,那么新 AOF 文件在主機重啟后就會消失,新的指令就不會生效。若將新指令同時寫入到舊 AOF 文件中,由于舊 AOF 文件是存儲在硬盤上的,那么在 Redis 重啟后依然能獲取到舊 AOF 文件中的數據,新執行的指令也就會生效,保證了數據完整性。這也就是 AOF 比 RDB 可靠的體現;
- 若在執行?bgrewriteaof 之前就已經有子進程在進行 AOF 重寫操作,那么就不會執行此次重寫;
- 若在執行?bgrewriteaof 之前已經有子進程在進行 RDB 重寫操作,那么會等待 RDB 重寫執行完再執行 AOF 重寫操作。
8. 混合持久化
由于 AOF 文件中的數據是以文本形式存儲的,那么在啟動 Redis 時讀取 AOF 文件中的內容所消耗的時間就會變多,于是可以采取使用 RDB 文件存儲方式,即使用二進制存儲數據,那么就會加快文件的讀取速度。
在 Redis 的配置文件中,若將 aof_use_rdb_preamble 設置為 yes,就表示以二進制形式存儲數據。Redis 默認?aof_use_rdb_preamble 為 yes。