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