Redis緩沖區(qū)溢出及解決方案分享
緩沖區(qū)(buffer),是內(nèi)存空間的一部分。也就是說,在內(nèi)存空間中預(yù)留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數(shù)據(jù),這部分預(yù)留的空間就叫做緩沖區(qū)。
一、Redis緩沖區(qū)溢出影響
在Redis中,主要有三個場景用到了緩沖區(qū)的概念。
在客戶端和服務(wù)器端之間進行通信時,用來暫存客戶端發(fā)送的命令數(shù)據(jù),或者是服務(wù)器端返回給客戶端的數(shù)據(jù)結(jié)果 在主從節(jié)點間進行數(shù)據(jù)同步時,Redis使用緩沖區(qū)來暫存主節(jié)點接收的寫命令和數(shù)據(jù) 在Redis進行AOF持久化的時候Redis為了避免頻繁寫磁盤同樣用到了緩沖區(qū)的概念
緩沖區(qū)概念最初是操作系統(tǒng)為了緩和 CPU 與 I/O 設(shè)備速度不匹配的矛盾,提高 CPU 和 I/O 設(shè)備的并行性而引入的。
對于高速設(shè)備與低速設(shè)備的不匹配,勢必會讓高速設(shè)備花時間等待低速設(shè)備。有了緩沖區(qū)的概念就可以很好的解決這個問題。緩沖區(qū)也是生產(chǎn)者消費者模式的重要體現(xiàn)。
1、緩沖區(qū)溢出導(dǎo)致網(wǎng)絡(luò)連接關(guān)閉
如果 qubf-free 耗盡,就會引起客戶端輸入緩沖區(qū)溢出,Redis 的處理方法就是把客戶端連接關(guān)閉,導(dǎo)致的結(jié)果就是業(yè)務(wù)程序無法進行數(shù)據(jù)存取。
2、緩沖區(qū)溢出導(dǎo)致命令數(shù)據(jù)丟失或者崩潰
通常情況下,會有很多的客戶端連接,當客戶端連接占用的內(nèi)存總量,超過了 Redis 的 maxmemory 配置時,就會觸發(fā) Redis 進行數(shù)據(jù)淘汰,影響業(yè)務(wù)程序的訪問性能。
甚至多個客戶端會導(dǎo)致 Redis 內(nèi)存占用過大,也會導(dǎo)致內(nèi)存溢出問題,進而引起 Redis 崩潰。
二、客戶端緩沖區(qū)
客戶端緩沖區(qū)又有兩個,輸入緩沖區(qū)和輸出緩沖區(qū),都是為了解決客戶端和服務(wù)器端的請求發(fā)送和處理速度不匹配所設(shè)置的。
輸入緩沖區(qū)暫存的是客戶端發(fā)來的命令,其常見的溢出原因有兩個:
寫入了BigKey,如一次性寫入了百萬級別的哈?;蚣蠑?shù)據(jù),超過了緩沖區(qū)的大小 服務(wù)端處理請求的速度過慢導(dǎo)致阻塞,無法及時處理請求,使得客戶端發(fā)送的請求在緩沖區(qū)內(nèi)越積越多。
輸出緩沖區(qū)暫存的是 Redis 主線程要返回給客戶端的數(shù)據(jù)。
這個數(shù)據(jù),既有簡單且大小固定的 OK 響應(yīng)(例如,執(zhí)行 SET 命令)或報錯信息,也有大小不固定的、包含具體數(shù)據(jù)的執(zhí)行結(jié)果(例如,執(zhí)行 HGET 命令)
輸出緩沖區(qū)常見的溢出原因有三種:
返回BigKey的大量結(jié)果 執(zhí)行了某些不合理的命令 緩沖區(qū)大小設(shè)置不合理
從輸入和輸出緩沖區(qū)常見導(dǎo)致溢出的原因來看,BigKey是最可能導(dǎo)致溢出的原因,因此我們應(yīng)該盡量避免使用BigKey。
對于輸入緩沖區(qū),因為沒有辦法改變其大小(默認每個客戶端1G),我們只能通過控制命令的發(fā)送和處理速度入手,盡量避免阻塞。
對于輸出緩沖區(qū)則要避免一些返回大量結(jié)果的命令的使用如KEYS,MONITOR等,同時可以通過調(diào)整輸出緩沖區(qū)的大小來避免溢出。
三、復(fù)制緩沖區(qū)
復(fù)制緩沖區(qū)是用于Redis主從節(jié)點之間復(fù)制時使用的。由于主從節(jié)點間的數(shù)據(jù)復(fù)制包括全量復(fù)制和增量復(fù)制兩種。因此復(fù)制緩沖區(qū)也分為復(fù)制緩沖區(qū)和復(fù)制積壓緩沖區(qū)兩種。
1、復(fù)制緩沖區(qū)
在全量復(fù)制過程中,主節(jié)點在向從節(jié)點傳輸 RDB 文件的同時,會繼續(xù)接收客戶端發(fā)送的寫命令請求。這些寫命令就會先保存在復(fù)制緩沖區(qū)中,等 RDB 文件傳輸完成后,再發(fā)送給從節(jié)點去執(zhí)行。主節(jié)點上會為每個從節(jié)點都維護一個復(fù)制緩沖區(qū),來保證主從節(jié)點間的數(shù)據(jù)同步。
對于復(fù)制緩沖區(qū),如果主庫傳輸 RDB 文件以及從庫加載 RDB 文件耗時長,同時主庫接收的寫命令操作較多,就會導(dǎo)致復(fù)制緩沖區(qū)被寫滿而溢出。
想要避免復(fù)制緩沖區(qū)溢出,一方面我們可以控制主節(jié)點保存的數(shù)據(jù)量大小,這樣可以讓RDB文件的傳輸以及從庫加載時間變快,以避免復(fù)制緩沖區(qū)累積過多命令。
也可以根據(jù)主節(jié)點的數(shù)據(jù)量大小、主節(jié)點的寫負載壓力和主節(jié)點本身的內(nèi)存大小來更合理的設(shè)置復(fù)制緩沖區(qū)的大小來避免溢出,此外,由于主節(jié)點會為每一個從節(jié)點設(shè)置一個復(fù)制緩沖區(qū),如果集群中的從節(jié)點數(shù)非常多的話,主節(jié)點的內(nèi)存開銷就會非常大,因此我們應(yīng)該盡量避免一個主節(jié)點有過多的從節(jié)點。
2、復(fù)制積壓緩沖區(qū)
增量復(fù)制時,主節(jié)點和從節(jié)點進行常規(guī)同步時,會把寫命令也暫存在復(fù)制積壓緩沖區(qū)中。如果從節(jié)點和主節(jié)點間發(fā)生了網(wǎng)絡(luò)斷連,等從節(jié)點再次連接后,可以從復(fù)制積壓緩沖區(qū)中同步尚未復(fù)制的命令操作。
需要注意的是復(fù)制積壓緩沖區(qū)是一個大小有限的環(huán)形緩沖區(qū)。
當主節(jié)點把復(fù)制積壓緩沖區(qū)寫滿后,會覆蓋緩沖區(qū)中的舊命令數(shù)據(jù)。此時會造成主從節(jié)點的數(shù)據(jù)不一致。
針對這個問題,一般的應(yīng)對的方法是調(diào)大復(fù)制積壓緩沖區(qū)的大小,這個大小的計算方式一般可以使用
緩沖區(qū)大小=(主庫寫入命令速度 * 操作大小 - 主從庫間網(wǎng)絡(luò)傳輸命令速度 * 操作大?。? 2
如果如果并發(fā)請求量非常大,調(diào)整緩沖區(qū)大小的方式還不能解決,那么可以考慮使用切片集群的方式解決
四、AOF緩沖區(qū)
AOF緩沖區(qū)是Redis在AOF持久化的所設(shè)置的緩沖區(qū),AOF緩沖區(qū)也有兩種AOF緩沖區(qū)和AOF重寫緩沖區(qū)。
1、AOF緩沖區(qū)
我們都知道,即使是固態(tài)硬盤,它的讀寫速度也是與內(nèi)存的讀寫速度相差很多的。AOF緩沖區(qū)就主要是Redis用來解決主進程執(zhí)行命令速度與磁盤寫入速度不同步所設(shè)置的,通過AOF緩沖區(qū)可以有效地避免頻繁對硬盤進行讀寫,進而提升性能。Redis在AOF持久化的時候,會先把命令寫入到AOF緩沖區(qū),然后通過回寫策略來寫入硬盤AOF文件。
AOF緩沖區(qū)的溢出可能與磁盤寫入速度有關(guān)系,也可能與AOF回寫策略有關(guān)系,當大量命令積壓在AOF緩沖區(qū),超過其設(shè)置閾值之后,就會導(dǎo)致緩沖區(qū)溢出,想要避免這個問題,我們可以通過調(diào)整回寫策略,或者調(diào)整AOF緩沖區(qū)大小的方式來解決。
2、AOF重寫緩沖區(qū)
AOF重寫緩沖區(qū)是Redis在子進程進行AOF重寫的時候,父進程接受了新的命令,此時會把命令寫入AOF重寫緩沖區(qū),等到子進程重寫完成后,把AOF重寫緩沖區(qū)命令追加到新的AOF文件中。
AOF重寫緩沖區(qū)的溢出與AOF重寫期間主進程所處理的命令數(shù)有關(guān)系,當AOF重寫期間Redis主進程處理了大量的命令,這些命令都會寫入AOF重寫緩沖區(qū),當超過設(shè)定閾值之后,就會導(dǎo)致溢出。
避免AOF重寫緩沖區(qū)的溢出我們也可以通過調(diào)整AOF重寫緩沖區(qū)的大小來解決。
五、總結(jié)
這篇文章總結(jié)了緩沖區(qū)的概念,分析了Redis的三個緩沖區(qū),以及可能造成其溢出的原因和解決辦法。
對于緩沖區(qū)溢出其實主要有兩種原因,一是緩沖區(qū)大小不夠,二是消費者處理的速度太慢,而生產(chǎn)者生產(chǎn)的太快,導(dǎo)致大量內(nèi)容積壓在緩沖區(qū),進而導(dǎo)致溢出。
而解決方案就可以通過調(diào)整緩沖區(qū)的大小,或者調(diào)整生產(chǎn)者與消費者之間生產(chǎn)與處理消息的速度,使其處于一個相對平衡的狀態(tài)。
Redis緩沖區(qū)溢出是常見的問題,但可以通過多種方式來解決。最常見的方法是增加Redis內(nèi)存容量和優(yōu)化緩沖區(qū)刷新策略。同時,使用更好的硬件設(shè)備和升級Redis版本也可以幫助解決這個問題。當然,預(yù)防比治療更為重要,因此,在使用Redis時,需要注意數(shù)據(jù)的寫入速度和Redis服務(wù)器的配置。只有做好這些預(yù)防工作,才能避免Redis緩沖區(qū)溢出問題的出現(xiàn)。
到此這篇關(guān)于Redis緩沖區(qū)溢出及解決方案分享的文章就介紹到這了,更多相關(guān)Redis緩沖區(qū)溢出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!