溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Redis緩沖區(qū)機(jī)制實(shí)例分析

發(fā)布時(shí)間:2022-06-02 13:47:06 來(lái)源:億速云 閱讀:101 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹“Redis緩沖區(qū)機(jī)制實(shí)例分析”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“Redis緩沖區(qū)機(jī)制實(shí)例分析”文章能幫助大家解決問(wèn)題。

Redis緩沖區(qū)機(jī)制

Redis中的緩沖區(qū)機(jī)制就是為了平衡客戶端發(fā)送命令和服務(wù)端處理命令的速度差異,如果客戶端寫(xiě)入過(guò)快或者服務(wù)端讀取過(guò)慢這就會(huì)導(dǎo)致緩沖區(qū)溢出,緩沖區(qū)一旦溢出將引發(fā)一系列的性能問(wèn)題,下面我們?cè)敿?xì)聊聊。

客戶端緩沖機(jī)制

Redis為每一個(gè)客戶端都分配了一個(gè)輸入緩沖區(qū)和輸出緩沖區(qū),輸入緩沖區(qū)會(huì)把客戶端的請(qǐng)求命令暫存起來(lái),Redis主線程會(huì)從緩沖區(qū)中獲取命令,當(dāng)Redis處理完命令后會(huì)將結(jié)果寫(xiě)入到輸出緩沖區(qū)中,通過(guò)輸出緩沖區(qū)返回給客戶端,如下所示

Redis緩沖區(qū)機(jī)制實(shí)例分析

應(yīng)對(duì)輸入緩沖區(qū)溢出

輸入緩沖區(qū)溢出一般就是兩種情況

  • 寫(xiě)入數(shù)據(jù)過(guò)快,或者寫(xiě)入bigkey的數(shù)據(jù)占滿數(shù)據(jù)緩沖區(qū)。

  • 服務(wù)端處理數(shù)據(jù)過(guò)慢,一般是主線程被阻塞無(wú)法正常響應(yīng)客戶端請(qǐng)求。

查看輸入緩沖區(qū)信息

我們可以采用client list查看輸入緩沖區(qū)的具體信息

127.0.0.1:6379> client list
id=13 addr=127.0.0.1:50484 fd=7 name= age=1136 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default
id=14 addr=127.0.0.1:50486 fd=8 name= age=1114 idle=6 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client user=default

每連接上一個(gè)客戶端就會(huì)多一條輸入緩沖區(qū)信息,上面命令是我本地連接兩個(gè)客戶端的結(jié)果,我們查看緩沖區(qū)主要關(guān)注內(nèi)存相關(guān)的兩個(gè)參數(shù)

  • qbuf:緩沖區(qū)已經(jīng)使用的長(zhǎng)度(字節(jié)為單位,0表示沒(méi)有分配緩沖區(qū))。

  • qbuf-free:緩沖區(qū)剩余空閑空間(字節(jié)為單位),上面一個(gè)客戶端的qbuf=26,空閑緩沖區(qū)qbuf-free=32742,那么分配內(nèi)存總大小為26+32742=32768字節(jié)也就是32KB。

如果輸入緩沖區(qū)信息中的qbuf-free很小并且qbuf很大時(shí)就需要注意了,這時(shí)輸入緩沖區(qū)可能已經(jīng)快溢出了,如果此時(shí)還有大量請(qǐng)求寫(xiě)入輸入緩沖區(qū),Redis的解決辦法就是關(guān)閉和這個(gè)客戶端的連接,那么業(yè)務(wù)數(shù)據(jù)將無(wú)法正常存取。

而且還有一個(gè)問(wèn)題就是輸入緩沖區(qū)是每一個(gè)客戶端都會(huì)存在,那么當(dāng)所有客戶端的輸入緩沖區(qū)內(nèi)存總和超過(guò)了maxmemory配置,那么將引發(fā)內(nèi)存淘汰,部分淘汰的數(shù)據(jù)再次訪問(wèn)需要從后臺(tái)數(shù)據(jù)庫(kù)獲取,獲取的耗時(shí)肯定比Redis直接讀取慢的多,所以這也是Redis產(chǎn)生延遲的一個(gè)原因。

如何解決輸入緩沖區(qū)溢出

輸入緩沖區(qū)溢出本質(zhì)就是緩沖區(qū)的容量不夠,所以第一個(gè)思路就是擴(kuò)大輸入緩沖區(qū)的大小,很不幸Redis沒(méi)有提供給我們修改輸入緩沖區(qū)大小的配置,Redis要求每個(gè)客戶端的輸入緩沖區(qū)最大不能超過(guò)1G,注意是每個(gè)客戶端?。?!,如果客戶端的輸入緩沖區(qū)超過(guò)一個(gè)1G將關(guān)閉客戶端連接,所以這個(gè)是行不通的。

那就只能從客戶端發(fā)送數(shù)據(jù)的大小以及服務(wù)端處理命令的速度,客戶端需要避免bigkey的寫(xiě)入bigkey的劣勢(shì)太多一般都需要拆分,第二服務(wù)端的命令處理速度這個(gè)一般依賴于主線程是否阻塞,需要盡量的避免一些阻塞操作如AOF文件重寫(xiě),鍵值刪除,fork線程等等。

應(yīng)對(duì)輸出緩沖區(qū)溢出

對(duì)于服務(wù)端而言,客戶端的輸入信息通常都是不可預(yù)測(cè)的,但是輸出信息大多可以預(yù)測(cè),如Set命令返回信息只是一個(gè)簡(jiǎn)單的OK,又如一些報(bào)錯(cuò)信息,Redis為這些不變的返回信息分配了16KB的固定緩沖空間,也就是說(shuō)輸出緩沖區(qū)分為兩個(gè)部分一部分是輸出緩沖區(qū)固定返回信息,一部分是可變的返回信息。

輸出緩沖區(qū)溢出分為三種情況

  • 輸出bigkey等容量大的鍵值。

  • 客戶端執(zhí)行Monitor命令,監(jiān)控Redis執(zhí)行。

  • 緩沖區(qū)設(shè)置不合理。

bigkey是老生常談的一個(gè)問(wèn)題,當(dāng)服務(wù)端輸出一個(gè)bigkey或者keys這類命令,對(duì)輸出緩沖區(qū)的考驗(yàn)是非常大的,因?yàn)椴樵兊囊凰查g會(huì)占據(jù)輸入緩沖區(qū)大量的內(nèi)存空間。

Monitor命令的執(zhí)行

Monitor命令一般是一個(gè)debug命令,用來(lái)監(jiān)控Redis的具體執(zhí)行情況,能夠返回服務(wù)器處理的每一個(gè)命令。

127.0.0.1:6379> monitor
OK
1652184977.609761 [0 127.0.0.1:50484] "get" "name"
1652185391.529292 [0 127.0.0.1:50484] "set" "test" "lisi"
......

一直運(yùn)行monitor將一直占據(jù)輸出緩沖區(qū),也就是說(shuō)占據(jù)時(shí)間越長(zhǎng),越容易造成輸出緩沖區(qū)的溢出,所以Monitor命令僅僅只適用于調(diào)試環(huán)境,不能在生產(chǎn)上執(zhí)行這些命令。

輸出緩沖區(qū)設(shè)置不合理

輸入緩沖區(qū)的大小不能設(shè)置,但是輸出緩沖區(qū)的是可以設(shè)置的我們可以通過(guò)配置項(xiàng)client-output-buffer-limit來(lái)設(shè)置,設(shè)置的內(nèi)容就是兩部分

  • 緩沖區(qū)的內(nèi)存大小,當(dāng)超過(guò)緩沖區(qū)配置的大小,服務(wù)端會(huì)關(guān)閉和客戶端的連接。

  • 持續(xù)寫(xiě)入的時(shí)間限制和持續(xù)寫(xiě)入的容量限制,當(dāng)超過(guò)持續(xù)寫(xiě)入時(shí)間限制和容量限制,服務(wù)端也會(huì)強(qiáng)制關(guān)閉和客戶端的連接。

客戶端種類

在聊緩沖區(qū)配置時(shí),我們需要先了解下客戶端的種類,本文中強(qiáng)調(diào)的客戶端并不是單純指通過(guò)命令./redis-cli -c -h 127.0.0.1 -p 6379去連接Redis服務(wù)器這類客戶端稱為常規(guī)客戶端,我們還有通過(guò)消息訂閱Redis頻道的客戶端,還有一種最為特殊的主從同步,從節(jié)點(diǎn)也是一個(gè)特殊的客戶端稱為從節(jié)點(diǎn)客戶端。

配置項(xiàng)client-output-buffer-limit也是針對(duì)這三種,給出了不一樣的配置,如下所示

## 普通客戶端配置
client-output-buffer-limit normal 0 0 0
## 從節(jié)點(diǎn)客戶端配置
client-output-buffer-limit replica 256mb 64mb 60
## 消息訂閱頻道的客戶端
client-output-buffer-limit pubsub 32mb 8mb 60

######################配置解釋######################
## 第一個(gè)參數(shù):代表分配給客戶端的緩存大小,為0代表沒(méi)有限制
## 第二個(gè)參數(shù):表示持續(xù)寫(xiě)入的最大內(nèi)存,為0代表沒(méi)有限制
## 第三個(gè)參數(shù):表示持續(xù)寫(xiě)入的最長(zhǎng)時(shí)間,為0代表沒(méi)有限制

普通客戶端設(shè)置

普通客戶端就是傳輸?shù)囊恍┢胀ǖ闹噶?,一個(gè)指令發(fā)送完需要等待其返回后才會(huì)發(fā)送下一個(gè)指令,也就是說(shuō)只要不是返回的bigkey數(shù)據(jù),占用輸出緩沖區(qū)的內(nèi)存就極少,能夠立即發(fā)送給客戶端響應(yīng),所以一般正??蛻舳四J(rèn)配置都是0,也就是不限制。

消息訂閱頻道客戶端

當(dāng)訂閱頻道產(chǎn)生消息后,會(huì)將消息通過(guò)輸出緩沖區(qū)發(fā)送給客戶端,這種屬于非阻塞的方式,一瞬間可能有多個(gè)指令到達(dá),所以需要指定緩沖區(qū)大小。

如何解決輸出緩沖區(qū)溢出

到這里其實(shí)我們已經(jīng)能夠得到輸出緩沖區(qū)溢出的解決方案了

  • bigkey應(yīng)當(dāng)避免使用。

  • Monitor命令只在調(diào)試的時(shí)候使用,不能應(yīng)用到生產(chǎn)。

  • 合理設(shè)置輸出緩沖區(qū)上限、持續(xù)寫(xiě)入時(shí)間上限以及持續(xù)寫(xiě)入內(nèi)存容量上限。

主從集群中的緩沖區(qū)

除了輸入緩沖區(qū)和輸出緩沖區(qū)外在主從集群場(chǎng)景下還存在兩種緩沖區(qū),我們稱為復(fù)制緩沖區(qū)和復(fù)制積壓緩沖區(qū),這兩個(gè)緩沖區(qū)的溢出和輸入輸出緩沖區(qū)稍有不同。

復(fù)制緩沖區(qū)

復(fù)制緩沖區(qū)這個(gè)名詞看著很陌生,但是我們之前在聊主從同步時(shí)講過(guò),主從全量同步期間從節(jié)點(diǎn)會(huì)加載主節(jié)點(diǎn)的RDB文件,這時(shí)主節(jié)點(diǎn)同樣還能寫(xiě)入數(shù)據(jù),但是從節(jié)點(diǎn)在加載RDB文件沒(méi)辦法實(shí)時(shí)同步,所以Redis就為每一個(gè)從節(jié)點(diǎn)開(kāi)辟了一片空間,用來(lái)存放主從全量同步期間產(chǎn)生的操作命令,這就是replication buffer,也就是復(fù)制緩沖區(qū)。

Redis緩沖區(qū)機(jī)制實(shí)例分析

復(fù)制緩沖區(qū)溢出

復(fù)制緩沖區(qū)什么時(shí)候會(huì)溢出呢?

  • 當(dāng)從節(jié)點(diǎn)在加載RDB文件這個(gè)過(guò)程中如果存在大量的寫(xiě)操作就會(huì)造成復(fù)制緩沖區(qū)內(nèi)存溢出。

  • 從節(jié)點(diǎn)加載RDB文件的時(shí)間過(guò)長(zhǎng)。

發(fā)生溢出后,主節(jié)點(diǎn)會(huì)關(guān)閉與從節(jié)點(diǎn)的連接,導(dǎo)致全量同步失敗。

解決復(fù)制緩沖區(qū)溢出

控制主節(jié)點(diǎn)實(shí)例的大小,減小生成的RDB文件,這樣就能減少?gòu)墓?jié)點(diǎn)加載RDB文件的時(shí)間,減小復(fù)制緩沖區(qū)的壓力。

從節(jié)點(diǎn)其本質(zhì)就是主節(jié)點(diǎn)的特殊客戶端,所以使用的是輸出緩沖區(qū)(也就是指replication buffer),可以設(shè)置client-output-buffer-limit replica 256mb 64mb 60擴(kuò)大緩沖區(qū)大小。

注意:主節(jié)點(diǎn)上的復(fù)制緩沖區(qū)會(huì)為每一個(gè)從節(jié)點(diǎn)分配一個(gè),那么從節(jié)點(diǎn)的數(shù)量過(guò)多即使每個(gè)從節(jié)點(diǎn)沒(méi)有達(dá)到maxmemory,但累加的結(jié)果也會(huì)給主節(jié)點(diǎn)帶來(lái)內(nèi)存壓力

復(fù)制積壓緩沖區(qū)

復(fù)制積壓緩沖區(qū)溢出

主從集群在寫(xiě)操作時(shí)會(huì)將操作寫(xiě)入復(fù)制緩沖區(qū)和復(fù)制積壓緩沖區(qū)中,一旦網(wǎng)絡(luò)發(fā)送故障后恢復(fù)連接,在2.8版本之前主從節(jié)點(diǎn)會(huì)進(jìn)行全量同步開(kāi)銷(xiāo)非常大,所以2.8版本后還是采用了增量同步,僅僅將網(wǎng)絡(luò)斷開(kāi)這段時(shí)間的操作同步給從節(jié)點(diǎn),所以在網(wǎng)絡(luò)恢復(fù)連接后從節(jié)點(diǎn)會(huì)將自己的復(fù)制偏移量slave_repl_offset發(fā)送給主節(jié)點(diǎn),主節(jié)點(diǎn)將自身的寫(xiě)入偏移量master_repl_offset和slave_repl_offset在復(fù)制積壓緩沖區(qū)中做對(duì)比得到網(wǎng)絡(luò)斷連期間的操作。

復(fù)制積壓緩沖區(qū)又叫repl_backlog_buffer,是一個(gè)環(huán)形緩沖區(qū),同步示意圖如下。

Redis緩沖區(qū)機(jī)制實(shí)例分析

復(fù)制積壓緩沖區(qū)溢出其實(shí)也就是因?yàn)閺?fù)制積壓緩沖區(qū)是一個(gè)有限環(huán)形結(jié)構(gòu),一般主節(jié)點(diǎn)寫(xiě)入偏移量要大于從節(jié)點(diǎn)的讀取偏移量,但如果寫(xiě)入偏移量覆蓋了從節(jié)點(diǎn)的讀取偏移量這就引發(fā)了復(fù)制積壓緩沖區(qū)溢出。

解決復(fù)制積壓緩沖區(qū)溢出

一般是調(diào)整repl_backlog_size這個(gè)參數(shù)的大小,擴(kuò)大復(fù)制積壓緩沖區(qū)的大小,減小主節(jié)點(diǎn)寫(xiě)入偏移量覆蓋從節(jié)點(diǎn)讀取偏移量的風(fēng)險(xiǎn)。

關(guān)于“Redis緩沖區(qū)機(jī)制實(shí)例分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI