Redis被bgsave和bgrewriteaof阻塞的解決方法
Redis 是一個性能非常高效的內存 Key-Value 存儲服務, 同時它還具有兩個非常重要的特性: 1. 持久化; 2. Value 數據結構. 這兩個特性讓它在不少場景輕松擊敗了 Memcached 和 Casandra 等.
Redis 的持久化在兩種方式: Snapshotting(快照) 和 Append-only file(aof). 在一個采用了 aof 模式的 Redis 服務器上, 當執行 bgrewriteaof 對 aof 進行歸并優化時, 出現了 Redis 被阻塞的問題, 此時, Redis 無法提供任何讀取和寫入操作.
按字面理解, bgrewriteaof 是在后臺進行操作, 不應該影響 Redis 的正常服務. 原理也確實是這樣的, Redis 首先 fork 一個子進程, 并在該子進程里進行歸并和寫持久化存儲設備(如硬盤)的. 按照正常邏輯, 在一臺多核的機器上, 即使子進程占滿 CPU 和硬盤, 也不應該導致 Redis 服務阻塞啊!
其實, 問題就出在硬盤上.
Redis 服務設置了 appendfsync everysec, 主進程每秒鐘便會調用 fsync(), 要求內核將數據”確實”寫到存儲硬件里. 但由于子進程同時也在寫硬盤, 從而導致主進程 fsync()/write() 操作被阻塞, 最終導致 Redis 主進程阻塞了.
解決方法便是設置 no-appendfsync-on-rewrite yes, 在子進程處理和寫硬盤時, 主進程不調用 fsync() 操作. 注意, 即使進程不調用 fsync(), 系統內核也會根據自己的算法在適當的時機將數據寫到硬盤(Linux 默認最長不超過 30 秒).
【編輯推薦】